[BZOJ3779]重组病毒(LCT+DFS序线段树)

[BZOJ4817]树点涂色,只是多了换根操作,分类讨论下即可。

 #include<cstdio>
#include<algorithm>
#define lc ch[x][0]
#define rc ch[x][1]
#define ls (x<<1)
#define rs (ls|1)
#define lson ls,L,mid
#define rson rs,mid+1,R
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
typedef long long ll;
using namespace std; const int N=;
char op[];
ll tag[N<<],sm[N<<];
int n,m,u,v,x,rt,cnt,tim,rev[N],h[N],nxt[N<<],to[N<<];
int L[N],R[N],dep[N],fa[N][],ch[N][],sz[N],f[N];
void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } inline int rd(){
int x=; char ch=getchar(); bool f=;
while (ch<'' || ch>'') f|=ch=='-',ch=getchar();
while (ch>='' && ch<='') x=(x<<)+(x<<)+(ch^),ch=getchar();
return f ? -x : x;
} int jump(int x,int k){
for (int i=; ~i; i--) if (k&(<<i)) x=fa[x][i]; return x;
} void push(int x,int L,int R){
if (!tag[x]) return;
int mid=(L+R)>>;
sm[ls]+=tag[x]*(mid-L+); tag[ls]+=tag[x];
sm[rs]+=tag[x]*(R-mid); tag[rs]+=tag[x];
tag[x]=;
} void mdf(int x,int L,int R,int l,int r,int k){
if (L==l && r==R){ sm[x]+=1ll*k*(R-L+); tag[x]+=k; return; }
int mid=(L+R)>>; push(x,L,R);
if (r<=mid) mdf(lson,l,r,k);
else if (l>mid) mdf(rson,l,r,k);
else mdf(lson,l,mid,k),mdf(rson,mid+,r,k);
sm[x]=sm[ls]+sm[rs];
} ll que(int x,int L,int R,int l,int r){
if (L==l && r==R) return sm[x];
int mid=(L+R)>>; push(x,L,R);
if (r<=mid) return que(lson,l,r);
else if (l>mid) return que(rson,l,r);
else return que(lson,l,mid)+que(rson,mid+,r);
} void dfs(int x){
L[x]=++tim; dep[x]=dep[fa[x][]]+; sz[x]=;
rep(i,,) fa[x][i]=fa[fa[x][i-]][i-];
mdf(,,n,L[x],L[x],dep[x]);
For(i,x) if ((k=to[i])!=fa[x][]) fa[k][]=x,f[k]=x,dfs(k),sz[x]+=sz[k];
R[x]=tim;
} bool isrt(int x){ return (!f[x]) || (ch[f[x]][]!=x && ch[f[x]][]!=x); }
void put(int x){ swap(lc,rc); rev[x]^=; }
void push(int x){ if (rev[x]) put(lc),put(rc),rev[x]=; }
void pd(int x){ if (!isrt(x)) pd(f[x]); push(x); } void rot(int x){
int y=f[x],z=f[y],w=ch[y][]==x;
if (!isrt(y)) ch[z][ch[z][]==y]=x;
f[x]=z; f[y]=x; f[ch[x][w^]]=y;
ch[y][w]=ch[x][w^]; ch[x][w^]=y;
} void splay(int x){
pd(x);
while (!isrt(x)){
int y=f[x],z=f[y];
if (!isrt(y)) (ch[z][]==y)^(ch[y][]==x) ? rot(x) : rot(y);
rot(x);
}
} void work(int x,int k){
if (rt==x) mdf(,,n,,n,k);
else if (L[rt]>=L[x] && L[rt]<=R[x]){
int t=jump(rt,dep[rt]-dep[x]-);
if (L[t]>) mdf(,,n,,L[t]-,k);
if (R[t]<n) mdf(,,n,R[t]+,n,k);
}else mdf(,,n,L[x],R[x],k);
} int find(int x){
push(x);
while (lc) x=lc,push(x);
return x;
} void access(int x){
for (int y=; x; y=x,x=f[x]){
splay(x);
if (rc) work(find(rc),);
if (y) work(find(y),-);
rc=y;
}
} void mkrt(int x){ access(x); splay(x); put(x); } int main(){
freopen("bzoj3779.in","r",stdin);
freopen("bzoj3779.out","w",stdout);
n=rd(); m=rd();
rep(i,,n) u=rd(),v=rd(),add(u,v),add(v,u);
dfs(); rt=;
while (m--){
scanf("%s",op); x=rd();
if (op[]=='L') access(x);
if (op[]=='C') mkrt(x),rt=x;
if (op[]=='Q'){
if (rt==x) printf("%.10lf\n",.*que(,,n,,n)/n);
else if (L[rt]>=L[x] && L[rt]<=R[x]){
int t=jump(rt,dep[rt]-dep[x]-);
ll res1=L[t]> ? que(,,n,,L[t]-) : ;
ll res2=R[t]<n ? que(,,n,R[t]+,n) : ;
printf("%.10lf\n",.*(res1+res2)/(n-sz[t]));
}else printf("%.10lf\n",.*que(,,n,L[x],R[x])/sz[x]);
}
}
return ;
}
上一篇:[LeetCode] Binary Tree Preorder Traversal 二叉树的先序遍历


下一篇:.net中ckeditor的应用