bzoj 3779: 重组病毒

  一道好题~~

  一个点到根传染需要的时间是这段路径上不同颜色的数目,一个点子树到根平均传染时间就是加权平均数了(好像是废话)。

  所以只要用线段树维护dfs序就这个可以了,换根的话一个点的子树要么在dfs序中不变,要么被截成了[1,l)和(r,n]两段(当这个点为当前root的祖先),l和r即为包含当前根的这个点的那个儿子的dfs序中的st和ed,只要分类讨论一下就可以了。

  所以问题只剩什么时候在线段树上修改,我们发现1操作和LCT中的access操作很像,2操作就是make_root,每个splay就是一个相同的颜色段,那么一个点到根的距离就是LCT中虚边的个数,把虚边改实边子树-1,反过来子树+1,而LCT的复杂度是nlogn的,那直接做就好了。

  

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #define N 100005
  6 #define ll long long
  7 using namespace std;
  8 int head[N],nxt[N*2],ver[N*2],tot;int n,m;
  9 void addd(int a,int b)
 10 {
 11     tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ;
 12 }
 13 int rev[N],ch[N][2],root,L[N],R[N],fa[N],faa[N];
 14 bool isroot(int x)
 15 {
 16     return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
 17 }
 18 void push_down(int x)
 19 {
 20     if(rev[x])
 21     {
 22         rev[x]^=1;rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;
 23         swap(L[ch[x][0]],R[ch[x][0]]);
 24         swap(L[ch[x][1]],R[ch[x][1]]);
 25         swap(ch[x][0],ch[x][1]);
 26     }
 27     return ;
 28 }
 29 void push_up(int x)
 30 {
 31     if(!ch[x][0])L[x]=x;
 32     else L[x]=L[ch[x][0]];
 33     if(!ch[x][1])R[x]=x;
 34     else R[x]=R[ch[x][1]];
 35 }
 36 void rotate(int p)
 37 {
 38     int q=fa[p],y=fa[q],x=(ch[q][1]==p);
 39     ch[q][x]=ch[p][x^1];fa[ch[q][x]]=q;
 40     ch[p][x^1]=q;
 41     fa[p]=y;
 42     if(!isroot(q))
 43     {
 44         if(ch[y][1]==q)ch[y][1]=p;
 45         else ch[y][0]=p;
 46     }
 47     fa[q]=p;
 48     push_up(q);
 49 }
 50 int q[N],topp;
 51 void splay(int x)
 52 {
 53     q[++topp]=x;
 54     for(int i=x;!isroot(i);i=fa[i])q[++topp]=fa[i];
 55     while(topp)push_down(q[topp--]);
 56     for(int y;!isroot(x);rotate(x))
 57     {
 58         y=fa[x];
 59         if(!isroot(y))
 60         {
 61             if((ch[fa[y]][0]==y)^(ch[y][0]==x))rotate(x);
 62             else rotate(y);
 63         }
 64     }
 65     push_up(x);
 66 }
 67 struct node
 68 {
 69     ll lazy,sum;
 70 }a[N*10];
 71 int sz[N];
 72 int st[N],ed[N],z,jian[N],dep[N],top[N],son[N];
 73 int find(int x,int y)
 74 {
 75     while(top[y]!=top[x])
 76     {
 77         if(faa[top[y]]==x)return top[y];
 78         y=faa[top[y]];
 79     }
 80     return son[x];
 81 }
 82 void dfs(int x,int f)
 83 {
 84     st[x]=++z;jian[z]=dep[x];sz[x]=1;L[x]=R[x]=x;
 85     for(int i=head[x];i;i=nxt[i])
 86     {
 87         if(ver[i]==f)continue;
 88         fa[ver[i]]=x;dep[ver[i]]=dep[x]+1;faa[ver[i]]=x;
 89          
 90         dfs(ver[i],x);
 91         sz[x]+=sz[ver[i]];
 92         if(sz[ver[i]]>sz[son[x]])son[x]=ver[i];
 93     }
 94     ed[x]=z;
 95     return ;
 96 }
 97 void dffs(int x,int f,int tp)
 98 {
 99     top[x]=tp;
100     if(son[x])dffs(son[x],x,tp);
101     for(int i=head[x];i;i=nxt[i])
102     {
103         if(ver[i]==f||ver[i]==son[x])continue;
104         dffs(ver[i],x,ver[i]);
105     }
106 }
107 void pd(int x,int l,int mid,int r)
108 {
109     if(a[x].lazy)
110     {
111         a[x*2].sum+=a[x].lazy*(mid-l+1);
112         a[x*2+1].sum+=a[x].lazy*(r-mid);
113         a[x*2].lazy+=a[x].lazy;a[x*2+1].lazy+=a[x].lazy;
114         a[x].lazy=0;
115     }return ;
116 }
117 ll qur(int x,int l,int r,int lll,int rr)
118 {
119     if(rr<lll)return 0;
120     if(lll<=l&&rr>=r)
121     {
122         return a[x].sum;
123     }
124     int mid=(l+r)>>1;
125     pd(x,l,mid,r);
126     if(lll>mid)return qur(x*2+1,mid+1,r,lll,rr);
127     if(rr<=mid)return qur(x*2,l,mid,lll,rr);
128     return qur(x*2,l,mid,lll,rr)+qur(x*2+1,mid+1,r,lll,rr);
129 }
130 void add(int x,int l,int r,int lll,int rr,ll z)
131 {
132     if(rr<lll)return ;
133     if(lll<=l&&rr>=r)
134     {
135         a[x].sum+=z*(r-l+1);
136         a[x].lazy+=z;
137         return ;
138     }
139     int mid=(l+r)>>1;
140     pd(x,l,mid,r);
141     if(lll<=mid)add(x*2,l,mid,lll,rr,z);
142     if(rr>mid)add(x*2+1,mid+1,r,lll,rr,z);
143     a[x].sum=a[x*2].sum+a[x*2+1].sum;
144 }
145 void build(int x,int l,int r)
146 {
147     if(l==r)
148     {
149         a[x].sum=jian[l];
150         return ;
151     }
152     int mid=(l+r)>>1;
153     build(x*2,l,mid);build(x*2+1,mid+1,r);
154     a[x].sum=a[x*2].sum+a[x*2+1].sum;
155     return ;
156 }
157 void gao(int x,int z)
158 {
159     if(x==root)
160     {
161         add(1,1,n,1,n,z);
162     }
163     else if(st[x]<st[root]&&ed[x]>=ed[root])
164     {
165         int t=find(x,root);
166         add(1,1,n,1,st[t]-1,z);
167         add(1,1,n,ed[t]+1,n,z);
168     }
169     else
170     {
171         add(1,1,n,st[x],ed[x],z);
172     }
173 }
174 void access(int x)
175 {
176     for(int t=0;x;t=x,x=fa[x])
177     {
178         splay(x);
179         if(t)gao(L[t],-1);
180         if(ch[x][1])
181         {
182             gao(L[ch[x][1]],1);
183         }
184         ch[x][1]=t;
185         push_up(x);
186     }
187     return ;
188 }
189 void make_root(int x)
190 {
191     access(x);splay(x);
192     rev[x]^=1;swap(L[x],R[x]);
193     return ;
194 }
195 int qursize(int x)
196 {
197     if(x==root)return n;
198     if(st[x]<st[root]&&ed[x]>=ed[root])
199     {
200         int t=find(x,root);
201         return n-sz[t];
202     }
203     else return sz[x];
204 }
205 ll qurs(int x)
206 {
207     if(x==root)return qur(1,1,n,1,n);
208     if(st[x]<st[root]&&ed[x]>=ed[root])
209     {
210         int t=find(x,root);
211         return qur(1,1,n,1,st[t]-1)+qur(1,1,n,ed[t]+1,n);
212     }
213     return qur(1,1,n,st[x],ed[x]);
214 }
215 int main()
216 {
217     scanf("%d%d",&n,&m);
218     int t1,t2;
219     for(int i=1;i<n;i++)
220     {
221         scanf("%d%d",&t1,&t2);
222         addd(t1,t2);addd(t2,t1);
223     }
224     dep[1]=1;
225     dfs(1,-1);
226     build(1,1,n);
227     dffs(1,-1,1);
228     char c[10];root=1;int tmp;
229     for(int i=1;i<=m;i++)
230     {
231         scanf("%s",c+1);
232         scanf("%d",&tmp);
233         if(c[3]=='Q')
234         {
235             int size=qursize(tmp);
236             ll ss=qurs(tmp);
237             printf("%.10lf\n",((double)ss)/size);
238         }
239         else if(c[3]=='L')
240         {
241             access(tmp);
242              
243         }
244         else
245         {   
246             make_root(tmp);
247             root=tmp;
248         }
249     }
250     return 0;
251 }

 

  

posted @ 2017-02-15 11:38  SD_le  阅读(343)  评论(0编辑  收藏  举报
重置按钮