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 }

 

posted @ 2016-08-19 20:53  汪立超  阅读(306)  评论(0编辑  收藏  举报