%%%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; }