一道好题~~
一个点到根传染需要的时间是这段路径上不同颜色的数目,一个点子树到根平均传染时间就是加权平均数了(好像是废话)。
所以只要用线段树维护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 ",((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 }