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

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

  1 #include<cstdio>
  2 #include<algorithm>
  3 #define lc ch[x][0]
  4 #define rc ch[x][1]
  5 #define ls (x<<1)
  6 #define rs (ls|1)
  7 #define lson ls,L,mid
  8 #define rson rs,mid+1,R
  9 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 10 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
 11 typedef long long ll;
 12 using namespace std;
 13 
 14 const int N=100010;
 15 char op[10];
 16 ll tag[N<<2],sm[N<<2];
 17 int n,m,u,v,x,rt,cnt,tim,rev[N],h[N],nxt[N<<1],to[N<<1];
 18 int L[N],R[N],dep[N],fa[N][20],ch[N][2],sz[N],f[N];
 19 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
 20 
 21 inline int rd(){
 22     int x=0; char ch=getchar(); bool f=0;
 23     while (ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
 24     while (ch>='0' && ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
 25     return f ? -x : x;
 26 }
 27 
 28 int jump(int x,int k){
 29     for (int i=18; ~i; i--) if (k&(1<<i)) x=fa[x][i]; return x;
 30 }
 31 
 32 void push(int x,int L,int R){
 33     if (!tag[x]) return;
 34     int mid=(L+R)>>1;
 35     sm[ls]+=tag[x]*(mid-L+1); tag[ls]+=tag[x];
 36     sm[rs]+=tag[x]*(R-mid); tag[rs]+=tag[x];
 37     tag[x]=0;
 38 }
 39 
 40 void mdf(int x,int L,int R,int l,int r,int k){
 41     if (L==l && r==R){ sm[x]+=1ll*k*(R-L+1); tag[x]+=k; return; }
 42     int mid=(L+R)>>1; push(x,L,R);
 43     if (r<=mid) mdf(lson,l,r,k);
 44     else if (l>mid) mdf(rson,l,r,k);
 45         else mdf(lson,l,mid,k),mdf(rson,mid+1,r,k);
 46     sm[x]=sm[ls]+sm[rs];
 47 }
 48 
 49 ll que(int x,int L,int R,int l,int r){
 50     if (L==l && r==R) return sm[x];
 51     int mid=(L+R)>>1; push(x,L,R);
 52     if (r<=mid) return que(lson,l,r);
 53     else if (l>mid) return que(rson,l,r);
 54         else return que(lson,l,mid)+que(rson,mid+1,r);
 55 }
 56 
 57 void dfs(int x){
 58     L[x]=++tim; dep[x]=dep[fa[x][0]]+1; sz[x]=1;
 59     rep(i,1,18) fa[x][i]=fa[fa[x][i-1]][i-1];
 60     mdf(1,1,n,L[x],L[x],dep[x]);
 61     For(i,x) if ((k=to[i])!=fa[x][0]) fa[k][0]=x,f[k]=x,dfs(k),sz[x]+=sz[k];
 62     R[x]=tim;
 63 }
 64 
 65 bool isrt(int x){ return (!f[x]) || (ch[f[x]][0]!=x && ch[f[x]][1]!=x); }
 66 void put(int x){ swap(lc,rc); rev[x]^=1; }
 67 void push(int x){ if (rev[x]) put(lc),put(rc),rev[x]=0; }
 68 void pd(int x){ if (!isrt(x)) pd(f[x]); push(x); }
 69 
 70 void rot(int x){
 71     int y=f[x],z=f[y],w=ch[y][1]==x;
 72     if (!isrt(y)) ch[z][ch[z][1]==y]=x;
 73     f[x]=z; f[y]=x; f[ch[x][w^1]]=y;
 74     ch[y][w]=ch[x][w^1]; ch[x][w^1]=y;
 75 }
 76 
 77 void splay(int x){
 78     pd(x);
 79     while (!isrt(x)){
 80         int y=f[x],z=f[y];
 81         if (!isrt(y)) (ch[z][1]==y)^(ch[y][1]==x) ? rot(x) : rot(y);
 82         rot(x);
 83     }
 84 }
 85 
 86 void work(int x,int k){
 87     if (rt==x) mdf(1,1,n,1,n,k);
 88     else if (L[rt]>=L[x] && L[rt]<=R[x]){
 89         int t=jump(rt,dep[rt]-dep[x]-1);
 90         if (L[t]>1) mdf(1,1,n,1,L[t]-1,k);
 91         if (R[t]<n) mdf(1,1,n,R[t]+1,n,k);
 92     }else mdf(1,1,n,L[x],R[x],k);
 93 }
 94 
 95 int find(int x){
 96     push(x);
 97     while (lc) x=lc,push(x);
 98     return x;
 99 }
100 
101 void access(int x){
102     for (int y=0; x; y=x,x=f[x]){
103         splay(x);
104         if (rc) work(find(rc),1);
105         if (y) work(find(y),-1);
106         rc=y;
107     }
108 }
109 
110 void mkrt(int x){ access(x); splay(x); put(x); }
111 
112 int main(){
113     freopen("bzoj3779.in","r",stdin);
114     freopen("bzoj3779.out","w",stdout);
115     n=rd(); m=rd();
116     rep(i,2,n) u=rd(),v=rd(),add(u,v),add(v,u);
117     dfs(1); rt=1;
118     while (m--){
119         scanf("%s",op); x=rd();
120         if (op[2]=='L') access(x);
121         if (op[2]=='C') mkrt(x),rt=x;
122         if (op[2]=='Q'){
123             if (rt==x) printf("%.10lf
",1.*que(1,1,n,1,n)/n);
124             else if (L[rt]>=L[x] && L[rt]<=R[x]){
125                 int t=jump(rt,dep[rt]-dep[x]-1);
126                 ll res1=L[t]>1 ? que(1,1,n,1,L[t]-1) : 0;
127                 ll res2=R[t]<n ? que(1,1,n,R[t]+1,n) : 0;
128                 printf("%.10lf
",1.*(res1+res2)/(n-sz[t]));
129             }else printf("%.10lf
",1.*que(1,1,n,L[x],R[x])/sz[x]);
130         }
131     }
132     return 0;
133 }
原文地址:https://www.cnblogs.com/HocRiser/p/10300424.html