BZOJ 2243: [SDOI2011]染色(树剖||LCT)

题目链接:BZOJ 2243: [SDOI2011]染色

题意:

给你一棵树,每个点有个颜色,有两个操作。

1 询问一条路径有多少段颜色。

2 将一条路径全部染成一个颜色。

题解:

这题可以用树剖+线段树维护。

但是LCT超级好写。

要注意的就是rev那里要把左右颜色也要换一换。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;i++)
 3 #define mst(a,b) memset(a,b,sizeof(a))
 4 using namespace std;
 5 
 6 namespace LCT
 7 {
 8     const int N=1e5+7;
 9     int f[N],son[N][2],val[N],sum[N],tmp[N],lazy[N],lc[N],rc[N];
10     int g[N],v[N*2],nxt[N*2],ed;bool rev[N];
11     void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
12     void build(int x=1){
13         sum[x]=val[x];
14         for(int i=g[x];i;i=nxt[i])
15             if(!f[v[i]]&&v[i]!=1)f[v[i]]=x,build(v[i]);    
16     }
17     bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
18     void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]),swap(lc[x],rc[x]);rev[x]^=1;}
19     void add(int x,int c){if(!x)return;sum[x]=1;val[x]=lazy[x]=lc[x]=rc[x]=c;}
20     void pb(int x){
21         if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;
22         if(lazy[x])add(son[x][0],lazy[x]),add(son[x][1],lazy[x]),lazy[x]=0;
23     }
24     void up(int x){
25         sum[x]=1,lc[x]=rc[x]=val[x];
26         if(son[x][0])sum[x]+=sum[son[x][0]]-(val[x]==rc[son[x][0]]),lc[x]=lc[son[x][0]];
27         if(son[x][1])sum[x]+=sum[son[x][1]]-(val[x]==lc[son[x][1]]),rc[x]=rc[son[x][1]];
28     }
29     void rotate(int x){
30         int y=f[x],w=son[y][1]==x;
31         son[y][w]=son[x][w^1];
32         if(son[x][w^1])f[son[x][w^1]]=y;
33         if(f[y]){
34             int z=f[y];
35             if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x;
36         }
37         f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
38     }
39     void splay(int x){
40         int s=1,i=x,y;tmp[1]=i;
41         while(!isroot(i))tmp[++s]=i=f[i];
42         while(s)pb(tmp[s--]);
43         while(!isroot(x)){
44             y=f[x];
45             if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
46             rotate(x);
47         }
48         up(x);
49     }
50     void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);}
51     int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;}
52     void makeroot(int x){access(x);splay(x);rev1(x);}
53     void link(int x,int y){makeroot(x);f[x]=y;access(x);}
54     void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;up(x);}
55     void cut(int x,int y){makeroot(x);cutf(y);}
56     void update(int x,int y,int c){makeroot(x),access(y),splay(y),add(y,c);}
57     int ask(int x,int y){makeroot(x);access(y);splay(y);return sum[y];}
58 }
59 
60 using namespace LCT;
61 int n,m,x,y,c;
62 char op[3];
63 
64 int main()
65 {
66     scanf("%d%d",&n,&m);
67     F(i,1,n)scanf("%d",val+i),val[i]++;
68     F(i,2,n)
69     {
70         scanf("%d%d",&x,&y);
71         adg(x,y),adg(y,x);
72     }
73     build();
74     F(i,1,m)
75     {
76         scanf("%s",op);
77         if(*op=='Q')
78         {
79             scanf("%d%d",&x,&y);
80             printf("%d\n",ask(x,y));
81         }
82         else if(*op=='C')
83         {
84             scanf("%d%d%d",&x,&y,&c);c++;
85             update(x,y,c);
86         }
87     }
88     return 0;
89 }
View Code

 

posted @ 2017-10-19 20:59  bin_gege  阅读(199)  评论(0编辑  收藏  举报