• [sdoi 2017]树点涂色


    传送门

    Description

    Bob 有一棵(n)个点的有根树,其中(1)号点是根节点。Bob 在每个节点上涂了颜色,并且每个点上的颜色不同。

    定义一条路径的权值是,这条路径上的点(包括起点和终点)共有多少种不同的颜色。

    Bob 可能会进行这几种操作:

    • 1 x,把点(x)到根节点的路径上的所有的点染上一种没有用过的新颜色;
    • 2 x y,求 (x)(y) 的路径的权值;
    • 3 x,在以 (x) 为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。

    Bob 一共会进行 (m) 次操作。

    Solution

    1. 发现任何时刻,每种颜色都是一条链,考虑直接用lct维护,1 x就等同于access x

    2. 发现每次1 x操作时,修改的是若干个子树的(ans),线段树维护(dfs)上的答案

      access经过轻边是,对线段树进行区间修改即可

    3. 祖先答案中的颜色,必然出现在孩子的答案中,所以路径的答案可以看成是:

      [ans_x+ans_y-2*ans_{lca(x,y)}+1 ]

    4. 一个子树的答案直接区间求最值即可


    Code 

    #include<bits/stdc++.h>
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define reg register
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    const int MN=1e5+5;
    int N,M,L[MN],R[MN],dep[MN],fdfn[MN];
    class Seg
    {
    	int lazy[MN<<2],t[MN<<2];
    	void C(int x,int y){t[x]+=y;lazy[x]+=y;}
    	void down(int x){if(lazy[x])C(x<<1,lazy[x]),C(x<<1|1,lazy[x]),lazy[x]=0;}
    	void Modi(int x,int l,int r,int a,int b,int ad)
    	{
    		if(l==a&&r==b){C(x,ad);return;}
    		reg int mid=(l+r)>>1;down(x);
    		if(b<=mid)Modi(x<<1,l,mid,a,b,ad);
    		else if(a>mid)Modi(x<<1|1,mid+1,r,a,b,ad);
    		else Modi(x<<1,l,mid,a,mid,ad),Modi(x<<1|1,mid+1,r,mid+1,b,ad);
    		t[x]=max(t[x<<1],t[x<<1|1]);
    	}
    	int Q1(int x,int l,int r,int a,int b)
    	{
    		if(l==a&&r==b)return t[x];
    		reg int mid=(l+r)>>1;down(x);
    		if(b<=mid)return Q1(x<<1,l,mid,a,b);
    		else if(a>mid)return Q1(x<<1|1,mid+1,r,a,b);
    		else return max(Q1(x<<1,l,mid,a,mid),Q1(x<<1|1,mid+1,r,mid+1,b));
    	}
    	public:
    		void Build(int x,int l,int r)
    		{
    			if(l==r) return (void)(t[x]=dep[fdfn[l]]);
    			reg int mid=(l+r)>>1;
    			Build(x<<1,l,mid);Build(x<<1|1,mid+1,r);
    			t[x]=max(t[x<<1],t[x<<1|1]);
    		}
    		void md(int x,int ad){if(x)Modi(1,1,N,L[x],R[x],ad);}
    		int q(int x){return Q1(1,1,N,L[x],L[x]);}
    		int _q(int x){return Q1(1,1,N,L[x],R[x]);}
    }T;
    class Link_Cut_Tree
    {
    	int fa[MN],c[MN][2];
    	bool nrt(int x){return c[fa[x]][0]==x||c[fa[x]][1]==x;}
    	bool get(int x){return c[fa[x]][1]==x;}
    	void rtt(int x)
    	{
    		int y=fa[x],z=fa[y],l=get(x),r=l^1;if(nrt(y))c[z][get(y)]=x;fa[x]=z;
    		fa[c[x][r]]=y;c[y][l]=c[x][r];fa[y]=x;c[x][r]=y;
    	}
    	void Splay(int x)
    	{
    		for(;nrt(x);rtt(x))
    			if(nrt(fa[x])) rtt(get(fa[x])^get(x)?x:fa[x]);
    	}
    	int fir(int x){if(!x) return 0;while(c[x][0])x=c[x][0];return x;}
    	public:
    		void acs(int x){reg int i;for(i=0;x;x=fa[i=x])Splay(x),T.md(fir(c[x][1]),1),c[x][1]=i,T.md(fir(i),-1);}
    		void link(int x,int y){fa[x]=y;}
    }lct;
    class Tree
    {
    	int fa[MN],mx[MN],siz[MN],top[MN],ind;
    	std::vector<int> A[MN];
    	void dfs1(int x,int f)
    	{
    		reg int i;siz[x]=1;fa[x]=f;lct.link(x,f);dep[x]=dep[f]+1;
    		for(i=A[x].size()-1;~i;--i)if(A[x][i]^f)
    			dfs1(A[x][i],x),siz[x]+=siz[A[x][i]],siz[A[x][i]]>siz[mx[x]]?mx[x]=A[x][i]:0;
    	}
    	void dfs2(int x,int tp)
    	{
    		L[x]=++ind;fdfn[ind]=x;top[x]=tp;if(mx[x])dfs2(mx[x],tp);reg int i;
    		for(i=A[x].size()-1;~i;--i)if(A[x][i]!=fa[x]&&A[x][i]!=mx[x])dfs2(A[x][i],A[x][i]);
    		R[x]=ind;
    	}
    	public:
    		void ins(int x,int y){A[x].push_back(y);A[y].push_back(x);}
    		void build(){dfs1(1,0);dfs2(1,1);}
    		int lca(int x,int y)
    		{
    			while(top[x]^top[y])
    				dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
    			return dep[x]<dep[y]?x:y;
    		}
    }tree;
    int main()
    {
    	N=read();M=read();
    	reg int i,opt,x,y;
    	for(i=1;i<N;++i) x=read(),tree.ins(x,read());
    	tree.build();T.Build(1,1,N);
    	while(M--)
    	{
    		opt=read(),x=read();
    		if(opt==1)lct.acs(x);
    		if(opt==2)y=read(),printf("%d
    ",T.q(x)+T.q(y)+1-2*T.q(tree.lca(x,y)));
    		if(opt==3)printf("%d
    ",T._q(x));
    	}
    	return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    T100添加合计
    T100整单操作维护交运方式
    错误代码:11300001 数据集配置错误Query:ORA-01652: 无法通过 128 (在表空间 TEMP 中) 扩展 temp 段
    T100 技术汇总
    帆软取年月常用函数
    使用oracle DB_LINK的一个注意点
    单行拆转多行的查询
    SQL-Oracle内实现柱形图式的效果
    SQL-删除重复记录
    MERGE语法详解
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/bzoj_4817.html
Copyright © 2020-2023  润新知