BZOJ 2243
http://www.lydsy.com/JudgeOnline/showsource.php?id=2443124
树链剖分套线段树直接肝
注意合并过程
#include<cstdio> #include<algorithm> #define FOR(i,s,t) for(register int i=s;i<=t;++i) #define gc getchar() using std::swap; inline int max(int a,int b){return a>b?a:b;} inline int min(int a,int b){return a<b?a:b;} const int N=800011; char S[5]; int c[N]; int n,m,dfn_num,x,y,z; inline int read(){ char c;while(c=gc,c==' '||c=='\n');int data=c-48; while(c=gc,c>='0'&&c<='9')data=(data<<1)+(data<<3)+c-48;return data; } struct edge{ int to; edge *nxt; #define to(it) it->to #define add(x,y) (*++et=(edge){y,las[x]},las[x]=et) #define VIS(now) for(edge *it=las[now];it;it=it->nxt) }e[N],*las[N],*et=e; namespace Segment_Tree{ struct Tree{ int lc,rc,sum,tag; }tr[N]; inline void push_up(int k){ tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum; tr[k].lc=tr[k<<1].lc;tr[k].rc=tr[k<<1|1].rc; if(tr[k<<1].rc==tr[k<<1|1].lc)--tr[k].sum; } inline void push_down(int k){ if(!tr[k].tag)return; tr[k<<1].lc=tr[k<<1].rc=tr[k<<1|1].lc=tr[k<<1|1].rc=tr[k<<1].tag=tr[k<<1|1].tag=tr[k].tag; tr[k<<1].sum=tr[k<<1|1].sum=1; tr[k].tag=0; } inline void change(int k,int x,int y,int v,int l=1,int r=n){ push_down(k); if(x<=l&&r<=y){ tr[k].sum=1; tr[k].tag=tr[k].lc=tr[k].rc=v; return; } int mid=(l+r)>>1; if(x<=mid)change(k<<1,x,y,v,l,mid); if(mid<y)change(k<<1|1,x,y,v,mid+1,r); push_up(k); } inline int query(int k,int x,int y,int l=1,int r=n){ push_down(k); push_up(k); if(x<=l&&r<=y)return tr[k].sum; int mid=(l+r)>>1,ans=0; if(x<=mid)ans+=query(k<<1,x,y,l,mid); if(mid<y)ans+=query(k<<1|1,x,y,mid+1,r); if(x<=mid&&mid<y&&tr[k<<1].rc==tr[k<<1|1].lc)--ans; return ans; } inline int query_color(int k,int pos,int l=1,int r=n){ push_down(k); push_up(k); if(l==r)return tr[k].lc; int mid=(l+r)>>1; return pos<=mid?query_color(k<<1,pos,l,mid):query_color(k<<1|1,pos,mid+1,r); } }; using namespace Segment_Tree; namespace TCP{ int dep[N],sz[N],fa[N]; int top[N],xu[N]; inline void dfs1(int now){ sz[now]=1; VIS(now) if(!dep[to(it)]){ dep[to(it)]=dep[now]+1;fa[to(it)]=now; dfs1(to(it));sz[now]+=sz[to(it)]; } } inline void dfs2(int now,int chain){ register int i=0; top[now]=chain;xu[now]=++dfn_num; change(1,xu[now],xu[now],c[now]); VIS(now)if(dep[to(it)]>dep[now]&&sz[i]<sz[to(it)])i=to(it); if(!i)return; dfs2(i,chain); VIS(now)if(dep[to(it)]>dep[now]&&to(it)!=i)dfs2(to(it),to(it)); } inline int up_query(int x,int y){ int ans=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); ans+=query(1,xu[top[x]],xu[x]); if(query_color(1,xu[top[x]])==query_color(1,xu[fa[top[x]]]))--ans; x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); ans+=query(1,xu[x],xu[y]); return ans; } inline void up_change(int x,int y,int z){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); change(1,xu[top[x]],xu[x],z); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); change(1,xu[x],xu[y],z); } }; using namespace TCP; int main(){ n=read();m=read(); FOR(i,1,n)c[i]=read()+1; FOR(i,2,n){ x=read();y=read(); add(x,y);add(y,x); } dep[1]=1;dfs1(1);dfs2(1,1); while(m--){ scanf("%s",S); x=read();y=read(); if(S[0]=='Q') printf("%d\n",up_query(x,y)); else{ z=read()+1; up_change(x,y,z); } } return 0; }