%%%PoPoQQQ http://blog.csdn.net/popoqqq/article/details/45919545
”题目大意:给定一棵树,初始每个点都有一个颜色,支持三种操作:
1.将某个点到根的路径上所有点染上一种新的颜色
2.将某个点到根的路径上所有点染上一种新的颜色,然后把根设为这个点
3.定义一个点的代价为这个点到根路径上颜色的种类数,求某个点子树中所有点代价的平均值
容易发现这玩应就是个LCT,操作1就是Access,操作2就是Move_To_Root,代价就是一个点到根路径上的虚边数量+1
我们用LCT模拟上述操作,用线段树维护DFS序维护信息,一旦LCT中出现了虚实边的切换,就在DFS序上对应的子树+1/-1,查询就直接在线段树上查就行了“
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define V G[p].v
using namespace std;
typedef long long ll;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x)
{
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline void read(char *s)
{
char c=nc(); int len=0;
for (;!(c>='A' && c<='Z');c=nc());
for (len=0;c>='A' && c<='Z';s[++len]=c,c=nc()); s[++len]=0;
}
const int N=100005;
namespace BIT{
#define lowbit(x) ((x)&-(x))
ll maxn,c1[N],c2[N];
inline void init(int n){
maxn=n;
}
inline void add(int x,ll r){
for (int i=x;i<=maxn;i+=lowbit(i))
c1[i]+=r,c2[i]+=x*r;
}
inline void add(int l,int r,ll x){
if (l>r) return;
add(l,x); add(r+1,-x);
}
inline ll sum(int x){
ll ret1=0,ret2=0;
for (int i=x;i;i-=lowbit(i))
ret1+=c1[i],ret2+=c2[i];
return (x+1)*ret1-ret2;
}
inline ll sum(int l,int r){
if (l>r) return 0;
return sum(r)-sum(l-1);
}
}
struct edge{
int u,v,next;
};
edge G[N*2];
int head[N],inum;
inline void add(int u,int v,int p)
{
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
int n,Q,rt;
int clk,tid[N],last[N];
int fat[N][21],size[N],depth[N];
inline void Modify(int x,int val);
struct Splay{
struct node{
node *p,*ch[2],*fat;
int size,rev,idx;
bool dir() { return this==p->ch[1]; }
void setc(node *c,int d) { ch[d]=c; c->p=this; }
void update(){
size=ch[0]->size+ch[1]->size+1;
}
void reverse(){
rev^=1; swap(ch[0],ch[1]);
}
void pushdown(node *null) {
if (rev)
{
if (ch[0]!=null) ch[0]->reverse();
if (ch[1]!=null) ch[1]->reverse();
rev=0;
}
}
}*null;
node Mem[N];
Splay(){
null=Mem; null->p=null->ch[0]=null->ch[1]=null; null->size=0;
}
void rot(node *x){
if (x==null) return;
bool d=x->dir(); node *p=x->p;
if (p->p!=null) p->p->setc(x,p->dir()); else x->p=null;
p->setc(x->ch[d^1],d); x->setc(p,d^1); p->update(); x->update(); swap(x->fat,p->fat);
}
node *stk[N];int pnt;
void splay(node *x){
node *y=x; pnt=0;
while (y!=null) stk[++pnt]=y,y=y->p;
for (int i=pnt;i;i--)
stk[i]->pushdown(null);
while (x->p!=null)
if (x->p->p==null)
rot(x);
else
(x->dir()==x->p->dir())?(rot(x->p),rot(x)):(rot(x),rot(x));
}
void Solve(node *x,int val)
{
if (x==null) return;
x->pushdown(null);
while (x->ch[0]!=null) x=x->ch[0],x->pushdown(null);
Modify(x->idx,val);
}
node *Access(node *x){
node *y=null;
while (x!=null)
{
splay(x);
x->ch[1]->p=null; x->ch[1]->fat=x;;
Solve(x->ch[1],1);
x->setc(y,1); y->fat=null;
Solve(y,-1);
x->update();
y=x; x=x->fat;
}
return y;
}
}LCT;
Splay::node *pos[N];
inline void Init(int n){
for (int i=1;i<=n;i++)
{
pos[i]=LCT.Mem+i; pos[i]->size=1; pos[i]->idx=i;
pos[i]->p=pos[i]->ch[0]=pos[i]->ch[1]=pos[i]->fat=LCT.null;
}
}
inline int dfs(int u,int fa)
{
tid[u]=++clk; size[u]=1; depth[u]=depth[fa]+1; fat[u][0]=fa;
for (int k=1;k<=20;k++) fat[u][k]=fat[fat[u][k-1]][k-1];
BIT::add(tid[u],tid[u],depth[u]);
if (!fa) pos[u]->fat=LCT.null; else pos[u]->fat=pos[fa];
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
size[u]+=dfs(V,u);
last[u]=tid[u]+size[u]-1;
return size[u];
}
inline int LCA(int u,int v){
if (depth[u]<depth[v]) swap(u,v);
for (int k=20;~k;k--)
if ((depth[u]-depth[v])&(1<<k))
u=fat[u][k];
if (u==v) return v;
for (int k=20;~k;k--)
if (fat[u][k]!=fat[v][k])
u=fat[u][k],v=fat[v][k];
return fat[u][0];
}
inline int Fat(int x,int y){
for (int k=20;~k;k--)
if (depth[fat[x][k]]>depth[y])
x=fat[x][k];
return x;
}
inline void Modify(int x,int val)
{
if(x==rt)
{
BIT::add(1,n,val);
return ;
}
int lca=LCA(x,rt);
if(lca!=x)
BIT::add(tid[x],last[x],val);
else
{
int y=Fat(rt,x);
BIT::add(1,tid[y]-1,val);
BIT::add(last[y]+1,n,val);
}
}
inline ll Sum(int x)
{
if(x==rt)
return BIT::sum(1,n);
int lca=LCA(x,rt);
if(lca!=x)
return BIT::sum(tid[x],last[x]);
else
{
int y=Fat(rt,x);
return BIT::sum(1,tid[y]-1)+BIT::sum(last[y]+1,n);
}
}
inline ll Size(int x)
{
if(x==rt)
return n;
int lca=LCA(x,rt);
if(lca!=x)
return size[x];
else
{
int y=Fat(rt,x);
return n-size[y];
}
}
int main()
{
int iu,iv,x; char order[10]; ll ret,tot;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(Q); Init(n); BIT::init(n);
for (int i=1;i<n;i++) read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum);
dfs(1,0); rt=1;
// for (int i=1;i<=n;i++) printf("%lld ",BIT::sum(i,i)); printf("\n");
while (Q--)
{
read(order); read(x);
if (!strcmp(order+1,"RELEASE")){
LCT.Access(pos[x]);
}
else if (!strcmp(order+1,"RECENTER")){
LCT.Access(pos[x])->reverse(); rt=x;
}
else if (!strcmp(order+1,"REQUEST")){
ret=Sum(x);
tot=Size(x);
printf("%.10lf\n",(double)ret/tot);
}
// for (int i=1;i<=n;i++) printf("%lld ",BIT::sum(i,i)); printf("\n");
}
return 0;
}