题意:
n点无根树,2类操作:将节点a到节点b路径上所有点都染成颜色c、询问节点a到节点b路径上的颜色段数量。
题解:
有点恶心的链剖,可以用包含区间颜色段数,左端点颜色,右端点颜色的结构体存储查询的结果。首先是线段树节点除了要保存区间颜色段数还要保存左右端点颜色,再者是查询的时候要注意合并区间:在线段树查询时,如果递归左端点,就左合并递归结果,如果右端点就右合并;在树链查询时,从下往上左合并查询结果,两段分开处理,当两段都查询完时将一段的结果中的左右端点颜色交换,然后合并。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define inc(i,j,k) for(int i=j;i<=k;i++) 5 #define maxn 200000 6 using namespace std; 7 8 struct e{int t,n;}; e es[maxn];int ess,g[maxn]; 9 void pe(int f,int t){es[++ess]=(e){t,g[f]}; g[f]=ess; es[++ess]=(e){f,g[t]}; g[t]=ess;} 10 int fa[maxn],sz[maxn],dep[maxn],pos[maxn],top[maxn],v[maxn][2],sgs; 11 int l[maxn*4],r[maxn*4],ch[maxn*4][2],ll[maxn*4],rr[maxn*4],sm[maxn*4],tg[maxn*4]; 12 struct nd{ 13 int sm,l,r; 14 void plusr(nd d){ 15 sm=sm+d.sm+(r==d.l?-1:0); r=d.r; 16 } 17 void plusl(nd d){ 18 sm=sm+d.sm+(d.r==l?-1:0); l=d.l; 19 } 20 }; 21 void dfs(int x){ 22 sz[x]=1; for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]){ 23 dep[es[i].t]=dep[x]+1; fa[es[i].t]=x; dfs(es[i].t); sz[x]+=sz[es[i].t]; 24 } 25 } 26 void buildchain(int x,int ps){ 27 pos[x]=++sgs; top[x]=ps; v[sgs][1]=v[x][0]; int mx1,mx2=0; 28 for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]&&mx2<sz[es[i].t])mx2=sz[es[i].t],mx1=es[i].t; 29 if(mx2)buildchain(mx1,ps); 30 for(int i=g[x];i;i=es[i].n)if(es[i].t!=fa[x]&&es[i].t!=mx1)buildchain(es[i].t,es[i].t); 31 } 32 int lca(int x,int y){ 33 for(;top[x]!=top[y];x=fa[top[x]])if(dep[top[x]]<dep[top[y]])swap(x,y); 34 return dep[x]<dep[y]?x:y; 35 } 36 void update(int x){ 37 if(!x)return; if(!ch[x][0]&&!ch[x][1])sm[x]=0; 38 sm[x]=sm[ch[x][0]]+sm[ch[x][1]]+(rr[ch[x][0]]==ll[ch[x][1]]?-1:0); 39 ll[x]=ll[ch[x][0]]; rr[x]=rr[ch[x][1]]; 40 } 41 void pushdown(int x){ 42 if(!x||tg[x]==-1)return; int lc=ch[x][0],rc=ch[x][1]; 43 if(lc)sm[lc]=1,ll[lc]=rr[lc]=tg[x],tg[lc]=tg[x]; 44 if(rc)sm[rc]=1,ll[rc]=rr[rc]=tg[x],tg[rc]=tg[x]; tg[x]=-1; 45 } 46 void build(int x,int L,int R){ 47 if(L==R)l[x]=r[x]=L,ch[x][0]=ch[x][1]=0,ll[x]=rr[x]=v[L][1],tg[x]=-1,sm[x]=1;else{ 48 int M=(L+R)>>1; ch[x][0]=x<<1; ch[x][1]=x<<1|1; l[x]=L; r[x]=R; tg[x]=-1; 49 build(ch[x][0],L,M); build(ch[x][1],M+1,R); update(x); 50 } 51 } 52 nd query(int x,int L,int R){ 53 pushdown(x); if(L<=l[x]&&r[x]<=R)return (nd){sm[x],ll[x],rr[x]}; 54 int M=(l[x]+r[x])>>1; nd q; 55 if(L<=M){ 56 q=query(ch[x][0],L,R); if(M<R)q.plusr(query(ch[x][1],L,R)); 57 }else if(M<R)q=(query(ch[x][1],L,R)); 58 return q; 59 } 60 void change(int x,int L,int R,int col){ 61 pushdown(x); if(L<=l[x]&&r[x]<=R){ll[x]=rr[x]=tg[x]=col,sm[x]=1; return;} 62 int M=(l[x]+r[x])>>1; if(L<=M)change(ch[x][0],L,R,col); 63 if(M<R)change(ch[x][1],L,R,col); update(x); 64 } 65 void init1(){ess=0; memset(g,0,sizeof(g));} 66 void init2(){fa[1]=0; dep[1]=0; dfs(1); sgs=0; buildchain(1,1); build(1,1,sgs);} 67 int querysum(int a,int b){ 68 if(a==b)return query(1,pos[a],pos[b]).sm; int c=lca(a,b); 69 nd q1; bool f=0; 70 while(dep[top[a]]>dep[top[c]]){ 71 if(!f)q1=query(1,pos[top[a]],pos[a]),f=1;else q1.plusl(query(1,pos[top[a]],pos[a])); 72 a=fa[top[a]]; 73 } 74 if(!f)q1=query(1,pos[c],pos[a]),f=1;else q1.plusl(query(1,pos[c],pos[a])); 75 nd q2; f=0; 76 while(dep[top[b]]>dep[top[c]]){ 77 if(! f)q2=query(1,pos[top[b]],pos[b]),f=1;else q2.plusl(query(1,pos[top[b]],pos[b])); 78 b=fa[top[b]]; 79 } 80 if(! f)q2=query(1,pos[c],pos[b]),f=1;else q2.plusl(query(1,pos[c],pos[b])); 81 swap(q1.l,q1.r); q1.plusr(q2); return q1.sm; 82 } 83 void changecol(int a,int b,int col){ 84 if(a==b){change(1,pos[a],pos[b],col);} int c=lca(a,b); 85 while(dep[top[a]]>dep[top[c]])change(1,pos[top[a]],pos[a],col),a=fa[top[a]]; 86 change(1,pos[c],pos[a],col); 87 while(dep[top[b]]>dep[top[c]])change(1,pos[top[b]],pos[b],col),b=fa[top[b]]; 88 change(1,pos[c],pos[b],col); 89 } 90 int n,m; char op[3]; 91 int main(){ 92 //freopen("test.txt","r",stdin); 93 scanf("%d%d",&n,&m); inc(i,1,n)scanf("%d",&v[i][0]); init1(); 94 inc(i,1,n-1){int a,b; scanf("%d%d",&a,&b); pe(a,b);} init2(); 95 inc(i,1,m){ 96 int a,b,c; scanf("%s%d%d",op,&a,&b); 97 if(op[0]=='Q'){printf("%d ",querysum(a,b));} 98 if(op[0]=='C'){scanf("%d",&c); changecol(a,b,c);} 99 } 100 return 0; 101 }
20160427