LOJ #6022. 重组病毒

Description

支持以下操作
1.access一个点
2.问一个点上面的重链的个数
3.换根 , 并access原来的根

Solution

对于重链个数 , 我们在 \(access\) 的时候对一个点的子树进行修改 .
换根的话 , 直接 $ mroot $就好了 , 注意要先 \(mroot\)\(rt=x\) , 因为要删去现在的根和 \(x\) 在原来的根下的 \(lca\) 以上那一段的贡献 .
然后查询就讨论一下根在子树内和子树外就行了 .
注意讨论修改和询问的 \(x=rt\) 的情况 .

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int head[N],nxt[N*2],to[N*2],num=0,n,m,L[N],R[N],DFN=0,ch[N][2],fa[N];
bool rev[N];ll t1[N],t2[N];int f[N][19],dep[N],rt=1;
inline void add(int x,int t){
	for(int i=x;i<=n;i+=(i&(-i)))t1[i]+=t,t2[i]+=x*t;
}
inline double qry(int x){
	ll s1=0,s2=0;
	for(int i=x;i;i-=(i&(-i)))s1+=t1[i],s2+=t2[i];
	return (double)(s1*(x+1)-s2);
}
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
inline void dfs(int x,int la){
	L[x]=++DFN;
	for(int i=1;i<=18;i++)f[x][i]=f[f[x][i-1]][i-1];
	for(int i=head[x],u;i;i=nxt[i]){
		if((u=to[i])==la)continue;
		fa[u]=f[u][0]=x;dep[u]=dep[x]+1;dfs(u,x);
	}
	add(L[x],1);add((R[x]=DFN)+1,-1);
}
inline bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline void rotate(int x){
	int y=fa[x];bool t=ch[y][1]==x;
	ch[y][t]=ch[x][!t];fa[ch[y][t]]=y;ch[x][!t]=y;fa[x]=fa[y];
   if(!isrt(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
	fa[y]=x;
}
inline void Rev(int x){if(x)rev[x]^=1,swap(ch[x][0],ch[x][1]);}
inline void pushdown(int x){if(rev[x])Rev(ch[x][0]),Rev(ch[x][1]),rev[x]=0;}
inline void Push(int x){if(!isrt(x))Push(fa[x]);pushdown(x);}
inline void splay(int x){
	Push(x);
	while(!isrt(x)){
		int y=fa[x],p=fa[y];
		if(isrt(y))rotate(x);
		else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x);
		else rotate(x),rotate(x);
	}
}
inline int lca(int x,int y){
	for(int i=18;i>=0;i--)if(dep[f[x][i]]>dep[y])x=f[x][i];
	return x;
}
inline void mdf(int x,int t){
	if(!x)return ;
	pushdown(x);
	while(ch[x][0])pushdown(x),x=ch[x][0];
	if(x==rt)add(1,t);
	if(L[rt]<=L[x] || L[rt]>R[x])add(L[x],t),add(R[x]+1,-t);
	else{
		int y=lca(rt,x);
		add(1,t);add(L[y],-t);add(R[y]+1,t);
	}
}
inline double query(int x){
	if(x==rt)return qry(n)/n;
	if(L[rt]<=L[x] || L[rt]>R[x])return (qry(R[x])-qry(L[x]-1))/(R[x]-L[x]+1);
	else{
		int y=lca(rt,x);
		return (qry(L[y]-1)+qry(n)-qry(R[y]))/(L[y]-1+n-R[y]);
	}
}
inline void access(int x){
	int y=0;
	while(x)splay(x),mdf(ch[x][1],1),ch[x][1]=y,mdf(y,-1),x=fa[y=x];
}
inline void mroot(int x){access(x);splay(x);Rev(x);}
int main(){
	freopen("shamate.in","r",stdin);
	freopen("shamate.out","w",stdout);
	int x,y;
	cin>>n>>m;
	for(int i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		link(x,y);link(y,x);
	}
	dfs(1,1);
	char op[10];
	while(m--){
		scanf("%s%d",op,&x);
		if(op[2]=='Q')printf("%.10lf\n",query(x));
		else if(op[2]=='L')access(x);
		else mroot(x),rt=x;
	}
	return 0;
}

posted @ 2018-08-04 19:35  PIPIBoss  阅读(376)  评论(0编辑  收藏  举报