【Foreign】染色 [LCT][线段树]

染色

Time Limit: 20 Sec  Memory Limit: 256 MB

Description

  

Input

  

Output

  

Sample Input

  13
  0 1
  0 2
  1 11
  1 10
  1 9
  9 12
  2 5
  5 8
  2 4
  2 3
  4 6
  4 7
  7
  q 0
  O 4
  q 6
  q 2
  O 9
  q 9
  q 2

Sample Output

  2.0000000000
  1.0000000000
  0.8571428571
  0.5000000000
  1.8571428571

HINT

  

Main idea

  询问x到根路径上不同颜色的个数,支持将x到根的路径上的点全部设为新的颜色。

Solution

  我们将边两端的点颜色相同的边设为实边不同的设为虚边。那么一次新增颜色的操作显然就是LCT的access操作!access的时候恰是虚边和实边的转换。

  那么我们只要用线段树维护每个点到根的贡献,结合dfs序来实现子树加,每次在LCT进行access的时候进行+-1修改,然后询问的时候用区间求和求得答案即可。

Code

  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<ctime>
  8 #include<cmath>
  9 using namespace std;  
 10 typedef long long s64;
 11 const int ONE=1500001;
 12 
 13 int n,m,x,y;
 14 int pos[ONE],size[ONE],Dep[ONE],dfn[ONE],cnt;
 15 s64 res;
 16 char ch[5];
 17 
 18 int lc[ONE],rc[ONE],fa[ONE];
 19 
 20 int get()
 21 {    
 22         int res=1,Q=1;char c;
 23         while( (c=getchar())<48 || c>57 )
 24         if(c=='-')Q=-1;
 25         res=c-48;
 26         while( (c=getchar())>=48 && c<=57 )
 27         res=res*10+c-48;
 28         return res*Q;
 29 }
 30 
 31 namespace tree
 32 {
 33         int next[ONE],first[ONE],go[ONE],tot;
 34         
 35         void Add(int u,int v)
 36         {
 37             next[++tot]=first[u];    first[u]=tot;    go[tot]=v;
 38             next[++tot]=first[v];    first[v]=tot;    go[tot]=u;
 39         }
 40         
 41         void Dfs(int u,int father)
 42         {
 43             pos[u] = ++cnt; dfn[cnt] = u;
 44             size[u] = 1;
 45             for(int e=first[u];e;e=next[e])
 46             {
 47                 int v=go[e];
 48                 if(v==father) continue;
 49                 Dep[v] = Dep[u] + 1;
 50                 fa[v] = u;
 51                 Dfs(v,u);
 52                 size[u] += size[v]; 
 53             }
 54         }
 55 }
 56 
 57 namespace Seg
 58 {
 59         struct power
 60         {
 61             s64 add,value;
 62         }Node[ONE];
 63         
 64         void pushdown(int i,int Q)
 65         {
 66             if(Node[i].add)
 67             {
 68                 Node[i<<1].add+=Node[i].add;
 69                 Node[i<<1|1].add+=Node[i].add;
 70                 Node[i<<1].value+=Node[i].add*(Q-Q/2);
 71                 Node[i<<1|1].value+=Node[i].add*(Q/2);
 72                 Node[i].add=0;
 73             }
 74         }
 75         
 76         void Build(int i,int l,int r)
 77         {
 78             if(l==r)
 79             {
 80                 Node[i].value = Dep[dfn[l]];
 81                 return;
 82             }
 83             int mid=(l+r)>>1;
 84             Build(i<<1,l,mid);    Build(i<<1|1,mid+1,r);
 85             Node[i].value=Node[i<<1].value+Node[i<<1|1].value;
 86         }
 87         
 88         void Update(int i,int l,int r,int L,int R,int x)
 89         {
 90             if(L<=l && r<=R)
 91             {
 92                 Node[i].add+=x;
 93                 Node[i].value+=(s64)(r-l+1)*x;
 94                 return;
 95             }
 96             
 97             pushdown(i,r-l+1);
 98             int mid=(l+r)>>1;
 99             if(L<=mid) Update(i<<1,l,mid,L,R,x);
100             if(mid+1<=R) Update(i<<1|1,mid+1,r,L,R,x);
101             Node[i].value=Node[i<<1].value+Node[i<<1|1].value;
102         }
103         
104         void Query(int i,int l,int r,int L,int R)
105         {
106             if(L<=l && r<=R)
107             {
108                 res+=Node[i].value;
109                 return;
110             }
111             pushdown(i,r-l+1);
112             int mid=(l+r)>>1;
113             if(L<=mid) Query(i<<1,l,mid,L,R);
114             if(mid+1<=R) Query(i<<1|1,mid+1,r,L,R);
115         } 
116 }
117 
118 namespace LCT
119 {
120         int is_real(int x)
121         {
122             return (lc[fa[x]]==x || rc[fa[x]]==x);
123         }
124         
125         void Turn(int x)
126         {
127             int y=fa[x],z=fa[y];
128             int b= x==lc[y] ? rc[x]:lc[x];
129             
130             fa[x]=z;    fa[y]=x;
131             if(b) fa[b]=y;
132             
133             if(z)
134             {
135                 if(y==lc[z]) lc[z]=x;
136                 else 
137                 if(y==rc[z]) rc[z]=x;
138             }
139             
140             if(x==lc[y]) rc[x]=y,lc[y]=b;
141             else lc[x]=y,rc[y]=b;
142         }
143         
144         void Splay(int x)
145         {
146             while(is_real(x))
147             {
148                 if(is_real(fa[x]))
149                 {
150                     if( (lc[fa[x]]==x) == (lc[fa[fa[x]]]==fa[x]) ) Turn(fa[x]);
151                     else Turn(x);
152                 }
153                 Turn(x);
154             }
155         }
156         
157         int find_root(int x)
158         {
159             while(lc[x]) x=lc[x];
160             return x;
161         }
162         
163         void access(int x)
164         {
165             for(int p=x,q=0; p; q=p,p=fa[p])
166             {
167                 Splay(p);
168                 if(rc[p])
169                 {
170                     int N=find_root(rc[p]);
171                     Seg::Update(1,1,n,pos[N],pos[N]+size[N]-1,+1);
172                 } 
173                 rc[p]=q;
174                 if(rc[p])
175                 {
176                     int N=find_root(rc[p]);
177                     Seg::Update(1,1,n,pos[N],pos[N]+size[N]-1,-1);
178                 }
179             }
180         }
181 }
182 
183 int main()
184 {
185         n=get();
186         for(int i=1;i<n;i++)
187         {
188             x=get();    y=get();
189             x++;    y++;
190             tree::Add(x,y);
191         }
192         tree::Dfs(1,0);
193         Seg::Build(1,1,n);
194         
195         m=get();
196         while(m--)
197         {
198             scanf("%s",ch);    x=get(); x++;
199             if(ch[0]=='O')
200             {
201                 LCT::access(x);
202             }
203             else
204             {
205                 res=0;
206                 Seg::Query(1,1,n,pos[x],pos[x]+size[x]-1);
207                 printf("%.10lf\n",(double)res/size[x]);
208             }
209         }
210         
211 }
View Code

 

posted @ 2017-03-03 19:12  BearChild  阅读(404)  评论(0编辑  收藏  举报