HINT:
$1leq N,Qleq 10^5$
原题:CodeChef November Challenge 2013 - MONOPLOY
题解:
其实这题是【SDOI2017】树点涂色的弱化版。。。
然后树点涂色这题甚至是[LOJ6022]【BZOJ3779】重组病毒的弱化版。。。
首先题目中的距离就是求路径上不同颜色的数目;
容易发现修改操作看起来很像LCT里的轻重边切换,那么以dfs序为下标建一颗线段树维护每个点到根节点的距离和,外面用一颗LCT维护,每次access轻重边切换的时候在线段树上修改即可。
时间复杂度:$O(nlog^2n)$
1A就是爽
代码:
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<queue>
7 #define inf 2147483647
8 #define eps 1e-9
9 using namespace std;
10 typedef long long ll;
11 struct edge{
12 int v,next;
13 }a[200001];
14 int n,q,u,v,x,tim=0,tot=0,head[100001],dep[100001],siz[100001],in[100001],out[100001],nmd[100001];
15 char op[3];
16 namespace sgt{
17 struct node{
18 ll v,laz;
19 }t[500001];
20 void pd(int u,int l,int r){
21 if(t[u].laz){
22 int mid=(l+r)/2;
23 t[u*2].v+=t[u].laz*(mid-l+1);
24 t[u*2].laz+=t[u].laz;
25 t[u*2+1].v+=t[u].laz*(r-mid);
26 t[u*2+1].laz+=t[u].laz;
27 t[u].laz=0;
28 }
29 }
30 void build(int l,int r,int u){
31 if(l==r){
32 t[u].v=dep[nmd[l]]-1;
33 return;
34 }
35 int mid=(l+r)/2;
36 build(l,mid,u*2);
37 build(mid+1,r,u*2+1);
38 t[u].v=t[u*2].v+t[u*2+1].v;
39 }
40 void updata(int l,int r,int u,int L,int R,ll v){
41 if(L<=l&&r<=R){
42 t[u].v+=v*(r-l+1);
43 t[u].laz+=v;
44 return;
45 }
46 int mid=(l+r)/2;
47 pd(u,l,r);
48 if(L<=mid)updata(l,mid,u*2,L,R,v);
49 if(mid<R)updata(mid+1,r,u*2+1,L,R,v);
50 t[u].v=t[u*2].v+t[u*2+1].v;
51 }
52 ll query(int l,int r,int u,int L,int R){
53 if(L<=l&&r<=R){
54 return t[u].v;
55 }
56 int mid=(l+r)/2;
57 ll ret=0;
58 pd(u,l,r);
59 if(L<=mid)ret=query(l,mid,u*2,L,R);
60 if(mid<R)ret+=query(mid+1,r,u*2+1,L,R);
61 return ret;
62 }
63 }
64 namespace lct{
65 struct node{
66 int son[2],fa,v;
67 }t[200001];
68 bool ntrt(int u){
69 return t[t[u].fa].son[0]==u||t[t[u].fa].son[1]==u;
70 }
71 bool lr(int u){
72 return t[t[u].fa].son[1]==u;
73 }
74 void rotate(int u){
75 int f=t[u].fa,ff=t[f].fa,ch=lr(u);
76 if(ntrt(f))t[ff].son[lr(f)]=u;
77 t[f].son[ch]=t[u].son[ch^1];
78 t[t[f].son[ch]].fa=f;
79 t[u].son[ch^1]=f;
80 t[f].fa=u;
81 t[u].fa=ff;
82 }
83 void splay(int u){
84 //printf("in splay %d %d
",u,t[u].fa);
85 while(ntrt(u)){
86 int f=t[u].fa;
87 if(ntrt(f))rotate(lr(u)^lr(f)?f:u);
88 rotate(u);
89 }
90 }
91 int get(int u){
92 while(t[u].son[0])u=t[u].son[0];
93 return u;
94 }
95 void access(int u){
96 for(int now=0;u;now=u,u=t[u].fa){
97 //printf("%d %d
",u,now);
98 splay(u);
99 if(t[u].son[1]){
100 int x=get(t[u].son[1]);
101 sgt::updata(1,n,1,in[x],out[x],1);
102 }
103 if(now){
104 int x=get(now);
105 sgt::updata(1,n,1,in[x],out[x],-1);
106 }
107 t[u].son[1]=now;
108 }
109 }
110 }
111 void add(int u,int v){
112 a[++tot].v=v;
113 a[tot].next=head[u];
114 head[u]=tot;
115 }
116 void dfs(int u,int fa,int dpt){
117 dep[u]=dpt;
118 siz[u]=1;
119 in[u]=++tim;
120 nmd[tim]=u;
121 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
122 int v=a[tmp].v;
123 if(v!=fa){
124 lct::t[v].fa=u;
125 dfs(v,u,dpt+1);
126 siz[u]+=siz[v];
127 }
128 }
129 out[u]=tim;
130 }
131 int main(){
132 memset(head,-1,sizeof(head));
133 scanf("%d",&n);
134 for(int i=1;i<n;i++){
135 scanf("%d%d",&u,&v);
136 u++,v++;
137 add(u,v);
138 add(v,u);
139 }
140 dfs(1,0,1);
141 sgt::build(1,n,1);
142 scanf("%d",&q);
143 for(int i=1;i<=q;i++){
144 scanf("%s%d",op,&x);
145 x++;
146 if(op[0]=='O')lct::access(x);
147 else printf("%.8lf
",(double)sgt::query(1,n,1,in[x],out[x])/(double)(siz[x]));
148 }
149 return 0;
150 }