bzoj3779: 重组病毒 link-cut-tree
这道题看了做了个神转换.....推荐个博客给各位大爷看看吧神犇传送门
代码敲了半天....题目也读了半天 线段树维护的东西很容易和lct混在一起 调了调能过也是很开心啊 运气比较好吧233
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; const int M=1<<17; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } int n,m,rt; int next[M],sum,father[M],deep[M],first[M],second[M]; struct Edge{int u,v,from;}e[2*M]; void ins(int a,int b){sum++; e[sum].u=a; e[sum].v=b; e[sum].from=next[a]; next[a]=sum;} void insert(int a,int b){ins(a,b); ins(b,a);} struct node{int l,r; LL sum,tag;}tr[M*2]; int c[M][2],fa[M],dfsum,rev[M]; void build(int x,int l,int r){ tr[x].l=l; tr[x].r=r; if(l==r) return ; int mid=(l+r)>>1; build(x<<1,l,mid); build(x<<1^1,mid+1,r); } void cal(int x,int w){tr[x].sum+=1LL*(tr[x].r-tr[x].l+1)*w;} void push_up(int x){tr[x].sum=tr[x<<1].sum+tr[x<<1^1].sum;} void push_down(int x){ if(!tr[x].tag) return ; int w=tr[x].tag; tr[x].tag=0; int l=x<<1,r=x<<1^1; tr[l].tag+=w; cal(l,w); tr[r].tag+=w; cal(r,w); } void push_add(int x,int L,int R,int w){ if(L>R) return ; if(L<=tr[x].l&&tr[x].r<=R){ cal(x,w); tr[x].tag+=1LL*w; return ; } if(tr[x].l==tr[x].r) return ; push_down(x); int mid=(tr[x].l+tr[x].r)>>1; if(L<=mid) push_add(x<<1,L,R,w); if(R>mid) push_add(x<<1^1,L,R,w); push_up(x); } LL push_ans(int x,int L,int R){ if(L>R) return 0; if(L<=tr[x].l&&tr[x].r<=R) return tr[x].sum; //if(tr[x].l==tr[x].r) return 0; LL ans=0; push_down(x); int mid=(tr[x].l+tr[x].r)>>1; if(L<=mid) ans+=push_ans(x<<1,L,R); if(R>mid) ans+=push_ans(x<<1^1,L,R); return ans; } void dfs(int x,int old){ father[x]=fa[x]=old; first[x]=++dfsum; deep[x]=deep[old]+1; push_add(1,first[x],first[x],deep[x]); for(int i=next[x];i;i=e[i].from) if(e[i].v!=old) dfs(e[i].v,x); second[x]=dfsum; } bool isrt(int x){return !x||(c[fa[x]][0]!=x&&c[fa[x]][1]!=x);}//0也算 void down(int x){ if(!rev[x]) return ; rev[x]=0; int l=c[x][0],r=c[x][1]; if(l) swap(c[l][0],c[l][1]),rev[l]^=1; if(r) swap(c[r][0],c[r][1]),rev[r]^=1; } void rotate(int x){ int y=fa[x],z=fa[y],l=0,r=1; if(c[y][1]==x) l=1,r=0; if(!isrt(y)) c[z][c[z][1]==y]=x; fa[y]=x; fa[x]=z; fa[c[x][r]]=y; c[y][l]=c[x][r]; c[x][r]=y; } int st[M],top; void splay(int x){ st[++top]=x; for(int i=x;!isrt(i);i=fa[i]) st[++top]=fa[i]; while(top) down(st[top--]); while(!isrt(x)){ int y=fa[x],z=fa[y]; if(!isrt(y)){ if(c[z][0]==y^c[y][0]==x) rotate(x); else rotate(y); } rotate(x); } } bool inson(int x,int y){return first[x]<=first[y]&&second[y]<=second[x];} int wson(int x,int y){ for(int i=next[x];i;i=e[i].from) if(e[i].v!=father[x]) if(first[e[i].v]<=first[y]&&second[y]<=second[e[i].v]) return e[i].v; return 0; } void add(int x,int w){ if(x==rt) push_add(1,1,n,w); else if(inson(x,rt)){ int p=wson(x,rt); push_add(1,1,first[p]-1,w); push_add(1,second[p]+1,n,w); } else push_add(1,first[x],second[x],w); } int find(int x){ while(c[x][0]) down(x),x=c[x][0]; return x; } void acs(int x){ int y=0; while(x){ splay(x); if(c[x][1]) add(find(c[x][1]),1); if(y) add(find(y),-1); c[x][1]=y; y=x; x=fa[x]; } } double addup(int x){ if(x==rt) return (double)push_ans(1,1,n)/n; if(inson(x,rt)){ int p=wson(x,rt); return ((double)push_ans(1,1,first[p]-1)+(double)push_ans(1,second[p]+1,n))/(n-(second[p]-first[p]+1)); } else return (double)push_ans(1,first[x],second[x])/(second[x]-first[x]+1); } void mrt(int x){splay(x); rt=x; swap(c[x][0],c[x][1]); rev[x]^=1;} int main() { int x,y; n=read(); m=read(); for(int i=1;i<n;i++) x=read(),y=read(),insert(x,y); rt=1; build(1,1,n); dfs(1,0); char ch[15]; for(int i=1;i<=m;i++){ scanf("%s",ch); x=read(); if(ch[2]=='Q') printf("%.10lf\n",addup(x)); else{ acs(x); if(ch[2]=='C') mrt(x); } } return 0; }