题意:
分析:
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=200100;
typedef long long ll;
int fa[N],c[N][2],rev[N],q[N];
int dep[N],a[N][21],h[N],w[N],lst[N],tmp[N];
ll sum[N*4];int tag[N*4],sz[N*4];
int n,m,tot,x,y,tm,root=1;
struct edge{int y,next;}g[N];
char s[100];
void adp(int x,int y){
g[++tot].y=y;
g[tot].next=h[x];
h[x]=tot;
}
void dfs(int x){
fa[x]=a[x][0];w[x]=++tm;
tmp[tm]=tmp[w[a[x][0]]]+1;
for (int i=h[x];i;i=g[i].next)
if (g[i].y!=a[x][0]){
dep[g[i].y]=dep[x]+1;
a[g[i].y][0]=x;
dfs(g[i].y);
}
lst[x]=tm;
}
/*----------------线段树-------------------*/
void pushup(int rt){
sum[rt]=sum[2*rt]+sum[2*rt+1];
}
void tagg(int rt,int val){
sum[rt]+=(ll)val*sz[rt];
tag[rt]+=val;
}
void pushdown(int rt){
if (tag[rt]){
tagg(2*rt,tag[rt]);
tagg(2*rt+1,tag[rt]);
tag[rt]=0;
}
}
void build(int rt,int l,int r){
if (l==r){sum[rt]=tmp[l],sz[rt]=1;return;}
int mid=(l+r)>>1;
build(2*rt,l,mid);build(2*rt+1,mid+1,r);
pushup(rt);sz[rt]=sz[2*rt]+sz[2*rt+1];
}
void change(int rt,int l,int r,int ll,int rr,int val){
if (ll>rr) return;
if (ll==l && r==rr){tagg(rt,val);return;}
pushdown(rt);
int mid=(l+r)>>1;
if (ll<=mid) change(2*rt,l,mid,ll,min(rr,mid),val);
if (rr> mid) change(2*rt+1,mid+1,r,max(mid+1,ll),rr,val);
pushup(rt);
}
void change(int rt,int k){
if (rt==root) change(1,1,n,1,n,k); else
if (w[root]>w[rt] && w[root]<=lst[rt]){
int t=root;
for (int i=20;i>=0;i--)
if ((dep[t]-dep[rt]-1)&(1<<i))
t=a[t][i];
change(1,1,n,1,w[t]-1,k);
change(1,1,n,lst[t]+1,n,k);
} else change(1,1,n,w[rt],lst[rt],k);
}
ll query(int rt,int l,int r,int ll,int rr){
if (ll>rr) return 0;
if (ll==l && r==rr) return sum[rt];
pushdown(rt);
int mid=(l+r)>>1;long long res=0;
if (ll<=mid) res+=query(2*rt,l,mid,ll,min(mid,rr));
if (rr> mid) res+=query(2*rt+1,mid+1,r,max(mid+1,ll),rr);
return res;
}
double query(int rt){
if (rt==root) return 1.0*query(1,1,n,1,n)/n;
if (w[root]>w[rt] && w[root]<=lst[rt]){
int t=root;
for (int i=20;i>=0;i--)
if ((dep[t]-dep[rt]-1)&(1<<i))
t=a[t][i];
int size=w[t]-1+n-lst[t];
return 1.0*((query(1,1,n,1,w[t]-1)+query(1,1,n,lst[t]+1,n)))/size;
}
return 1.0*query(1,1,n,w[rt],lst[rt])/(lst[rt]-w[rt]+1);
}
/*--------------------线段树-------------------------*/
/*---------------------lct---------------------------*/
int isroot(int x){
return c[fa[x]][0]!=x && c[fa[x]][1]!=x;
}
void push_down(int x){
if (rev[x]){
rev[x]^=1;
rev[c[x][0]]^=1;
rev[c[x][1]]^=1;
swap(c[x][0],c[x][1]);
}
}
void rotate(int x){
int y=fa[x],z=fa[y];
int l,r;
if (c[fa[x]][0]==x)
l=0; else l=1;
r=l^1;
if (!isroot(y)) {
if (c[z][0]==y)
c[z][0]=x; else
c[z][1]=x;
}
fa[x]=z;fa[y]=x;
fa[c[x][r]]=y;
c[y][l]=c[x][r];
c[x][r]=y;
}
void splay(int x){
int top=0,t=x;
q[++top]=x;
while (!isroot(t)){
q[++top]=fa[t];
t=fa[t];
}
for (int i=top;i;i--)
push_down(q[i]);
while (!isroot(x)){
int y=fa[x],z=fa[y];
if (!isroot(y)) {
if ((c[z][0]==y)!=(c[y][0]==x))
rotate(x); else
rotate(y);
}
rotate(x);
}
}
int find(int x){
int t=x;push_down(x);
while (c[t][0]){
t=c[t][0];
push_down(t);
}
return t;
}
void access(int x){
int t=0;
while (x){
splay(x);
if (c[x][1]) change(find(c[x][1]),1);
c[x][1]=t;
if (t) change(find(t),-1);
t=x;x=fa[x];
}
}
void makeroot(int x){
access(x);
splay(x);
rev[x]^=1;
root=x;
}
/*---------------------lct-----------------------*/
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<n;i++){
scanf("%d%d",&x,&y);
adp(x,y);adp(y,x);
}
tmp[1]=1;dfs(1);
for (int j=1;j<=20;j++)
for (int i=1;i<=n;i++)
a[i][j]=a[a[i][j-1]][j-1];
build(1,1,n);
while (m--){
scanf("%s%d",s,&x);
if (s[2]=='L')
access(x);
if (s[2]=='C')
makeroot(x);
if (s[2]=='Q')
printf("%.10lf\n",query(x));
}
}