bzoj2243树链剖分+染色段数
终于做了一道不是一眼出思路的代码题(⊙o⊙)
之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱)
实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开线段树的时候记录一下就好了
事实上我开了一个node,并且写了一个mix还是大大减小了代码量(对于我这种手残党来说同时大大减小了错误率)
由于前几题做的都是树链剖分,并没有在这一方面出问题,然而线段树还是不熟练,刚写完的时候居然忘记down了(mdzz)
对wa了N遍的总结:
由于是树上两个点间的路径,既有向上的路也有向下的路,然而树剖下来的结果是按深度排的,所以在链上跑的时候会发现一段链的左右(l和r)有时候是相反的,在合并几条链的时候一定要注意(事实证明我这么多遍wa全是因为没有翻转链)
对这一类问题的总结:
对于每一段都考虑有用(会对周围产生影响)的信息,在染色段数中就是两端(因为可能和隔壁合并)
1 //加了一大堆斜杠的是第一遍写之后补的 2 #include <cstdio> 3 #include <iostream> 4 #define mid (l+r)/2 5 using namespace std; 6 int m=0,N=0,n,M,p,q,o; 7 int to[200001],nex[200001],fir[100001],son[100001],bro[100001],co[100001]; 8 int size[100001],l[100001],pos[100001],fa[100001],h[100001],top[100001]; 9 struct node{int s,l,r;bool b;}t[500000],ans[2]; 10 inline void add(int x,int y){to[++m]=y;nex[m]=fir[x];fir[x]=m;} 11 inline node mix(node x,node y){return (node){x.s+y.s-(x.r==y.l),x.l,y.r,0};} 12 int build(int now,int fat) 13 { 14 size[now]=1;fa[now]=fat;h[now]=h[fat]+1; 15 for(int i=fir[now];i;i=nex[i]) 16 if(to[i]!=fat) 17 size[now]+=build(to[i],now),bro[to[i]]=son[now],son[now]=to[i]; 18 return size[now]; 19 } 20 void pou(int now,int to) 21 { 22 l[++N]=now;pos[now]=N;top[now]=to; 23 int max=son[now]; 24 if(!max) return; 25 for(int i=bro[max];i;i=bro[i]) 26 if(size[i]>size[max]) max=i; 27 pou(max,to); 28 for(int i=son[now];i;i=bro[i]) 29 if(i!=max) pou(i,i); 30 } 31 void down(int now)//////////////////////////// 32 { 33 if(t[now].b) 34 { 35 t[now].b=0;t[now*2].b=t[now*2+1].b=1; 36 t[now*2].s=t[now*2+1].s=1; 37 t[now*2].l=t[now*2].r=t[now*2+1].l=t[now*2+1].r=t[now].l; 38 } 39 } 40 void work(int now,int l,int r,int x,int y,int z) 41 { 42 if(l==x && r==y) 43 { t[now]=(node){1,z,z,1}; return;} 44 down(now); 45 if(x<=mid) 46 work(now*2,l,mid,x,min(y,mid),z); 47 if(y>mid) 48 work(now*2+1,mid+1,r,max(x,mid+1),y,z); 49 t[now]=mix(t[now*2],t[now*2+1]); 50 } 51 node que(int now,int l,int r,int x,int y) 52 { 53 if(l==x && r==y) 54 return t[now]; 55 down(now); 56 if(y<=mid) return que(now*2,l,mid,x,y); 57 if(x>mid) return que(now*2+1,mid+1,r,x,y); 58 return mix(que(now*2,l,mid,x,mid),que(now*2+1,mid+1,r,mid+1,y)); 59 } 60 void solve(int x,int y,int z) 61 { 62 bool b=0;ans[0]=ans[1]=(node){0,-1,-1,0}; 63 while(top[x]!=top[y]) 64 { 65 if(h[top[x]]<h[top[y]]) swap(x,y),b=!b; 66 if(z==-1) 67 { 68 node tem=que(1,1,n,pos[top[x]],pos[x]); 69 if(!b) swap(tem.l,tem.r);/////////////////////////////// 70 if(ans[b].s==0) ans[b]=tem; 71 else 72 ans[b]=b?mix(tem,ans[b]):mix(ans[b],tem); 73 } 74 else 75 work(1,1,n,pos[top[x]],pos[x],z); 76 x=fa[top[x]]; 77 } 78 if(h[x]>h[y]) swap(x,y),b=!b;////////////////// 79 if(z==-1) 80 { 81 node tem=que(1,1,n,pos[x],pos[y]);b=!b;//////////////// 82 if(!b) swap(tem.l,tem.r); 83 if(ans[b].s==0) ans[b]=tem; 84 else 85 ans[b]=b?mix(tem,ans[b]):mix(ans[b],tem); 86 printf("%d\n",mix(ans[0],ans[1]).s); 87 } 88 else 89 work(1,1,n,pos[x],pos[y],z); 90 } 91 int main() 92 { 93 scanf("%d%d",&n,&M); 94 for(int i=1;i<=n;i++) 95 scanf("%d",&co[i]); 96 for(int i=1;i<n;i++) 97 scanf("%d%d",&p,&q),add(p,q),add(q,p); 98 build(1,0); 99 pou(1,1); 100 for(int i=1;i<=n;i++) 101 work(1,1,n,pos[i],pos[i],co[i]); 102 for(int i=1;i<=M;i++) 103 { 104 char ch=getchar(); 105 while(ch!='C' && ch!='Q') ch=getchar(); 106 if(ch=='C') 107 scanf("%d%d%d",&p,&q,&o),solve(p,q,o); 108 else 109 scanf("%d%d",&p,&q),solve(p,q,-1); 110 } 111 return 0; 112 }