• luogu P3703 [SDOI2017]树点涂色


    LINK:树点涂色

    还是由暴力的思路拓展出来。可以发现对于初始情况一个点的权值就是深度。

    可以发现每次1操作是 LCT的access操作。

    考虑2操作 求x到y的权值和。

    可以发现其实是求x的答案+y的答案-2*LCA(x,y)的答案+1

    为什么 考虑 lca和他们两条路径上的最后一个点颜色都不同 那么这样做显然少加了一个LCA的颜色。

    如果和他们其中一个相同 这样做 发现也少加了一个LCA的颜色。

    至于操作3 直接维护区间最大值即可。

    const int MAXN=100010;
    int n,Q,len,cnt;
    int lin[MAXN],c[MAXN][2],f[MAXN],ver[MAXN<<1],nex[MAXN<<1],dfn[MAXN],out[MAXN];
    int fa[MAXN],d[MAXN],sz[MAXN],son[MAXN],top[MAXN],v[MAXN];
    inline void add(int x,int y)
    {
    	ver[++len]=y;
    	nex[len]=lin[x];
    	lin[x]=len;
    }
    inline void dfs(int x,int father)
    {
    	sz[x]=1;fa[x]=father;d[x]=d[father]+1;
    	go(x)if(tn^father)
    	{
    		dfs(tn,x);
    		sz[x]+=sz[tn];
    		if(sz[tn]>sz[son[x]])son[x]=tn;
    	}
    }
    inline void dp(int x,int father)
    {
    	top[x]=father;dfn[x]=++cnt;v[cnt]=x;
    	if(son[x])dp(son[x],father);
    	go(x)if(tn!=fa[x]&&tn!=son[x])dp(tn,tn);
    	out[x]=cnt;
    }
    inline int LCA(int x,int y)
    {
    	while(top[x]^top[y])
    	{
    		if(d[top[x]]<d[top[y]])swap(x,y);
    		x=fa[top[x]];
    	}
    	return d[x]<d[y]?x:y;
    }
    struct seg{int tag,mx,l,r;}t[MAXN<<2];
    inline void spread(int p,int v){tag(p)+=v;mx(p)+=v;}
    inline void pushdown(int p)
    {
    	spread(zz,tag(p));
    	spread(yy,tag(p));
    	tag(p)=0;
    }
    inline void build(int p,int l,int r)
    {
    	l(p)=l;r(p)=r;
    	if(l==r){mx(p)=d[v[l]];return;}
    	int mid=(l+r)>>1;
    	build(zz,l,mid);build(yy,mid+1,r);
    	mx(p)=max(mx(zz),mx(yy));
    }
    inline void change(int p,int l,int r,int x)
    {
    	if(l<=l(p)&&r>=r(p)){spread(p,x);return;}
    	int mid=(l(p)+r(p))>>1;
    	if(tag(p))pushdown(p);
    	if(l<=mid)change(zz,l,r,x);
    	if(r>mid)change(yy,l,r,x);
    	mx(p)=max(mx(zz),mx(yy));
    }
    inline int ask(int p,int x)
    {
    	if(l(p)==r(p))return mx(p);
    	int mid=(l(p)+r(p))>>1;
    	if(tag(p))pushdown(p);
    	if(x<=mid)return ask(zz,x);
    	return ask(yy,x);
    }
    inline int ask(int p,int l,int r)
    {
    	if(l<=l(p)&&r>=r(p))return mx(p);
    	int mid=(l(p)+r(p))>>1,w=0;
    	if(tag(p))pushdown(p);
    	if(l<=mid)w=ask(zz,l,r);
    	if(r>mid)w=max(w,ask(yy,l,r));
    	return w;
    }
    inline int pd(int x){return c[f[x]][1]==x||c[f[x]][0]==x;}//判断x是否为根.
    inline void rotate(int x)
    {
    	int old=f[x],oldf=f[old],k=c[old][1]==x;
    	c[old][k]=c[x][k^1];c[x][k^1]=old;
    	if(pd(old))c[oldf][c[oldf][1]==old]=x;
    	if(c[old][k])f[c[old][k]]=old;
    	f[old]=x;f[x]=oldf;
    }
    inline void splay(int x)
    {
    	while(pd(x))
    	{
    		if(pd(f[x]))rotate((c[f[x]][1]==x)^(c[f[f[x]]][1]==f[x])?x:f[x]);
    		rotate(x);
    	}
    }
    inline int findroot(int x)
    {
    	splay(x);
    	while(c[x][0])x=c[x][0];
    	splay(x);return x;
    }
    inline void access(int x)
    {
    	int y=0;
    	while(x)
    	{
    		splay(x);
    		if(c[x][1])
    		{
    			int w=c[x][1];
    			c[x][1]=0;
    			w=findroot(w);
    			change(1,dfn[w],out[w],1);
    		}
    		if(y)
    		{
    			y=findroot(y);
    			change(1,dfn[y],out[y],-1);
    		}
    		c[x][1]=y;
    		y=x;x=f[x];
    	}
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	//freopen("1.out","w",stdout);
    	get(n);get(Q);
    	rep(2,n,i)
    	{
    		int x,y;
    		get(x);get(y);
    		//cout<<x<<' '<<y<<endl;
    		add(x,y);add(y,x);
    	}
    	dfs(1,0);dp(1,1);
    	build(1,1,n);
    	rep(1,n,i)f[i]=fa[i];
    	rep(1,Q,i)
    	{
    		int op,x,y;
    		get(op);get(x);
    		if(op==1)access(x);
    		if(op==2)get(y),put(ask(1,dfn[x])+ask(1,dfn[y])-ask(1,dfn[LCA(x,y)])*2+1);
    		if(op==3)put(ask(1,dfn[x],out[x]));
    	}
    	return 0;
    }
    

    复杂度nlog^2.

  • 相关阅读:
    OpenCV中的绘图函数
    整理不错的opencv博客
    opencv中的函数
    这是一个学习前端技术的网站
    HDU1520 Anniversary party(树形DP入门)
    CF1255C League of Leesins(图论)
    HDU4725 The Shortest Path in Nya Graph(最短路分层)
    1288C Two Arrays
    CF1294D MEX maxiszing
    CF1295C Obtain the String
  • 原文地址:https://www.cnblogs.com/chdy/p/12670062.html
Copyright © 2020-2023  润新知