P2486 [SDOI2011]染色
阿新 • • 發佈:2021-01-11
連結
調了好久。。。
我平常寫平衡樹時 \(push\) \(tag\) 的操作都習慣把 \(rev\) 陣列清零,但在 \(LCT\) 中不行,因為 \(rev\) 儲存了節點間的父子關係,直接清零會改變樹的結構。
\(\frak{code}\)
#include<bits/stdc++.h> #define IL inline #define LL long long #define ls(x) ch[x][0] #define rs(x) ch[x][1] using namespace std; const int N=1e5+3; int n,m; IL int in(){ char c;int f=1; while((c=getchar())<'0'||c>'9') if(c=='-') f=-1; int x=c-'0'; while((c=getchar())>='0'&&c<='9') x=x*10+c-'0'; return x*f; } struct LCT{ int fa[N],ch[N][2],rev[N],tag[N],col[N],lc[N],rc[N],sum[N]; IL int chk(int x){return rs(fa[x])==x;} IL int noroot(int x){return ls(fa[x])==x||rs(fa[x])==x;} IL void pushup(int x){ if(ls(x)) lc[x]=lc[ls(x)];else lc[x]=col[x]; if(rs(x)) rc[x]=rc[rs(x)];else rc[x]=col[x]; sum[x]=sum[ls(x)]+sum[rs(x)]+1; if(ls(x)) sum[x]-=(col[x]==rc[ls(x)]); if(rs(x)) sum[x]-=(col[x]==lc[rs(x)]); } IL void Rev(int x){rev[x]^=1,swap(ls(x),rs(x)),swap(lc[x],rc[x]);} IL void Tag(int x,int v){tag[x]=col[x]=lc[x]=rc[x]=v,sum[x]=1;} IL void pushdown(int x){ if(tag[x]){ if(ls(x)) Tag(ls(x),tag[x]); if(rs(x)) Tag(rs(x),tag[x]); tag[x]=0; } if(rev[x]){ if(ls(x)) Rev(ls(x)); if(rs(x)) Rev(rs(x)); rev[x]=0; } } IL void rotate(int x){ int y=fa[x],z=fa[y],k=chk(x),w=ch[x][k^1]; if(noroot(y)) ch[z][chk(y)]=x; if(w) fa[w]=y; fa[y]=x,fa[x]=z,ch[x][k^1]=y,ch[y][k]=w; pushup(y),pushup(x); } void pushall(int x){ if(noroot(x)) pushall(fa[x]); pushdown(x); } IL void splay(int x){ pushall(x); while(noroot(x)){ int y=fa[x]; if(noroot(y)) rotate(chk(x)^chk(y)?x:y); rotate(x); } } IL void access(int x){for(int y=0;x;x=fa[y=x]) splay(x),rs(x)=y,pushup(x);} IL void makeroot(int x){access(x),splay(x),Rev(x);} IL void split(int x,int y){makeroot(x),access(y),splay(y);} IL void link(int x,int y){makeroot(x),fa[x]=y;} }T; int main() { char op[5];int x,y,z; n=in(),m=in(); for(int i=1;i<=n;++i) T.col[i]=T.lc[i]=T.rc[i]=in(),T.sum[i]=1; for(int i=1;i<n;++i) T.link(in(),in()); while(m--){ scanf("%s",op+1),x=in(),y=in(); if(op[1]=='Q') T.split(x,y),printf("%d\n",T.sum[y]); else T.split(x,y),T.Tag(y,in()); } return 0; }
附上一年多前寫的樹剖程式碼(那時真的 \(naive\),程式碼好笨拙啊qwq
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; struct hh{ int next,to; }lin[maxn<<1]; struct kk{ int left,right,num; }a[maxn<<2]; int siz[maxn],fa[maxn],d[maxn],son[maxn],numm[maxn]; int top[maxn],seg[maxn],rev[maxn],fir[maxn],nn,n,m,ans,z,last[4][3]; char sign[maxn<<2]; inline int read() { char c; while((c=getchar())<'0'||c>'9'); int x=c-'0'; while((c=getchar())>='0'&&c<='9') x=x*10+c-'0'; return x; } void init(int x,int y) { lin[++nn].next=fir[x]; fir[x]=nn; lin[nn].to=y; } void dfs1(int s,int f) { int u; siz[s]=1,d[s]=d[f]+1,fa[s]=f; for(int i=fir[s];i;i=lin[i].next) { u=lin[i].to; if(u!=f){ dfs1(u,s); siz[s]+=siz[u]; if(siz[u]>siz[son[s]]) son[s]=u; } } } void dfs2(int f) { int u=son[f]; if(u){ seg[u]=++seg[0]; rev[seg[0]]=u; top[u]=top[f]; dfs2(u); } for(int i=fir[f];i;i=lin[i].next) { u=lin[i].to; if(!top[u]){ seg[u]=++seg[0]; rev[seg[0]]=u; top[u]=u; dfs2(u); } } } void pd(int k) { a[k].left=a[k<<1].left,a[k].right=a[k<<1|1].right; a[k].num=a[k<<1].num+a[k<<1|1].num; if(a[k<<1].right==a[k<<1|1].left) --a[k].num; } void build(int k,int l,int r) { if(l==r){ a[k].left=a[k].right=numm[rev[l]],a[k].num=1;return; } int mid=l+r>>1; build(k<<1,l,mid),build(k<<1|1,mid+1,r); pd(k); } void push(int k) { a[k<<1].left=a[k<<1].right=a[k<<1|1].left=a[k<<1|1].right=a[k].left; a[k<<1].num=a[k<<1|1].num=1;sign[k]=0,sign[k<<1]=sign[k<<1|1]=1; } void query(int k,int l,int r,int ll,int rr) { if(l>=ll&&r<=rr){ ans+=a[k].num; if(l==ll) last[3][nn]=a[k].left;//fx if(r==rr) last[2][nn]=a[k].right;//x return; } if(sign[k]) push(k); int mid=l+r>>1; if(mid>=ll) query(k<<1,l,mid,ll,rr); if(mid<rr) query(k<<1|1,mid+1,r,ll,rr); if(mid>=ll&&mid<rr&&a[k<<1].right==a[k<<1|1].left) ans--; } void change(int k,int l,int r,int ll,int rr) { if(l>=ll&&r<=rr){ a[k].num=1,a[k].left=a[k].right=z,sign[k]=1;return; } if(sign[k]) push(k); int mid=l+r>>1; if(mid>=ll) change(k<<1,l,mid,ll,rr); if(mid<rr) change(k<<1|1,mid+1,r,ll,rr); pd(k); } void ask(int x,int y) { int fx=top[x],fy=top[y]; last[1][1]=last[1][2]=-1; while(fx!=fy) { if(d[fx]>d[fy]){ nn=1,query(1,1,seg[0],seg[fx],seg[x]); if(last[1][1]==last[2][1]) ans--; last[1][1]=last[3][1]; x=fa[fx],fx=top[x]; } else{ nn=2,query(1,1,seg[0],seg[fy],seg[y]); if(last[1][2]==last[2][2]) ans--; last[1][2]=last[3][2]; y=fa[fy],fy=top[y]; } } nn=2; if(d[x]>d[y]) swap(x,y),nn=1; query(1,1,seg[0],seg[x],seg[y]); if(last[1][nn]==last[2][nn]) ans--; if(last[3][nn]==last[1][3-nn]) ans--; } void solve(int x,int y) { int fx=top[x],fy=top[y]; while(fx!=fy){ if(d[fx]<d[fy]) swap(x,y),swap(fx,fy); change(1,1,seg[0],seg[fx],seg[x]); x=fa[fx],fx=top[x]; } if(d[x]>d[y]) swap(x,y); change(1,1,seg[0],seg[x],seg[y]); } int main() { int x,y; char flag[5]; n=read(),m=read(); for(int i=1;i<=n;++i) numm[i]=read(); for(int i=1;i<n;++i) { x=read(),y=read(); init(x,y),init(y,x); } dfs1(1,0),seg[0]=seg[1]=rev[1]=top[1]=1,dfs2(1),build(1,1,seg[0]); while(m--) { scanf("%s",flag); if(flag[0]=='Q'){ x=read(),y=read(),ans=0,ask(x,y),printf("%d\n",ans); } else{ x=read(),y=read(),z=read(),solve(x,y); } } return 0; }