Bob有一棵n个点的有根树,其中1号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路
径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:
1 x:
把点x到根节点的路径上所有的点染上一种没有用过的新颜色。
2 x y:
求x到y的路径的权值。
3 x
在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
Bob一共会进行m次操作
#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<bitset> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define ll long long using namespace std; int c[100010][2]; int fa[100010]; int tag[400010]; int f[100010][18]; int dep[100010]; int mx[400010]; int dfn; int tot; int x,y; int n,m; int opt; int head[100010]; int next[200010]; int to[200010]; int q[100010]; int s[100010]; int t[100010]; void add(int x,int y) { next[++tot]=head[x]; head[x]=tot; to[tot]=y; } void pushup(int rt) { mx[rt]=max(mx[rt<<1],mx[rt<<1|1]); } void pushdown(int rt) { if(tag[rt]) { tag[rt<<1]+=tag[rt]; tag[rt<<1|1]+=tag[rt]; mx[rt<<1]+=tag[rt]; mx[rt<<1|1]+=tag[rt]; tag[rt]=0; } } void build(int rt,int l,int r) { if(l==r) { mx[rt]=dep[q[l]]; return ; } int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); pushup(rt); } void change(int rt,int l,int r,int L,int R,int v) { if(L<=l&&r<=R) { tag[rt]+=v; mx[rt]+=v; return ; } pushdown(rt); int mid=(l+r)>>1; if(L<=mid) { change(rt<<1,l,mid,L,R,v); } if(R>mid) { change(rt<<1|1,mid+1,r,L,R,v); } pushup(rt); } int query(int rt,int l,int r,int L,int R) { if(L<=l&&r<=R) { return mx[rt]; } pushdown(rt); int mid=(l+r)>>1; int res=0; if(L<=mid) { res=max(res,query(rt<<1,l,mid,L,R)); } if(R>mid) { res=max(res,query(rt<<1|1,mid+1,r,L,R)); } return res; } int ask(int rt,int l,int r,int k) { if(l==r) { return mx[rt]; } pushdown(rt); int mid=(l+r)>>1; if(k<=mid) { return ask(rt<<1,l,mid,k); } else { return ask(rt<<1|1,mid+1,r,k); } } bool is_root(int rt) { return rt!=c[fa[rt]][0]&&rt!=c[fa[rt]][1]; } bool get(int rt) { return rt==c[fa[rt]][1]; } void rotate(int rt) { int x=fa[rt]; int y=fa[x]; int k=get(rt); if(!is_root(x)) { c[y][get(x)]=rt; } c[x][k]=c[rt][k^1]; fa[c[rt][k^1]]=x; c[rt][k^1]=x; fa[x]=rt; fa[rt]=y; } void splay(int rt) { for(int x;!is_root(rt);rotate(rt)) { if(!is_root(x=fa[rt])) { rotate(get(x)==get(rt)?x:rt); } } } void link(int x,int y) { fa[x]=y; } int find(int rt) { while(c[rt][0]) { rt=c[rt][0]; } return rt; } void access(int rt) { for(int x=0;rt;x=rt,rt=fa[rt]) { splay(rt); if(x) { int son=find(x); change(1,1,n,s[son],t[son],-1); } if(c[rt][1]) { int son=find(c[rt][1]); change(1,1,n,s[son],t[son],1); } c[rt][1]=x; } } void dfs(int x) { s[x]=++dfn; q[dfn]=x; for(int i=1;i<=17;i++) { f[x][i]=f[f[x][i-1]][i-1]; } for(int i=head[x];i;i=next[i]) { if(to[i]!=f[x][0]) { f[to[i]][0]=x; link(to[i],x); dep[to[i]]=dep[x]+1; dfs(to[i]); } } t[x]=dfn; } int lca(int x,int y) { if(dep[x]<dep[y]) { swap(x,y); } int d=dep[x]-dep[y]; for(int i=0;i<=17;i++) { if(d&(1<<i)) { x=f[x][i]; } } if(x==y) { return x; } for(int i=17;i>=0;i--) { if(f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } } return f[x][0]; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } dep[1]=1; dfs(1); build(1,1,n); while(m--) { scanf("%d",&opt); if(opt==1) { scanf("%d",&x); access(x); } else if(opt==2) { scanf("%d%d",&x,&y); int anc=lca(x,y); int ans=ask(1,1,n,s[x])+ask(1,1,n,s[y])-2*ask(1,1,n,s[anc])+1; printf("%d\n",ans); } else { scanf("%d",&x); printf("%d\n",query(1,1,n,s[x],t[x])); } } }
BZOJ4817[Sdoi2017]树点涂色——LCT+线段树
原文:https://www.cnblogs.com/Khada-Jhin/p/10650810.html