zoukankan      html  css  js  c++  java
  • bzoj3779: 重组病毒

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3779

    思路:RELEASE操作怎么给人一种access的感觉呢?

    “如果新变种在感染过程中尚未销毁过这类旧变种,需要先花费1单位时间分析旧变种,才能销毁”

    这不就是到根统计虚边条数+1吗

    继续看下去

    RECENTER好像就是换根,换完了正好要access一下

    REQUEST询问子树每个点到根的路径虚边数+1的平均值

    子树操作lct不滋磁

    拿个线段树维护一下dfs序就好了

    access无非就是减少一条或加上一条虚边,在线段树中区间加一加就好了

    换根之后线段树也是可以做的,要分情况讨论

    可以参见bzoj3083: 遥远的国度

    设当前根为root,要加/减虚边条数的子树根是x,w[x]是x的dfs序,last[x]表示 最初的树中 x的子树中的 最大dfs序

    1.x==root,直接对整棵树修改

    2.最初的树中,root在x的子树里,设既是x的儿子,又是root的祖先的点是y

    那么修改区间[1,w[y]-1],[last[y]+1,n](除去子树y的所有点)即可

    3.最初的树中,root不在x的子树里

    修改x的子树即可



    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>	
    const int maxn=100010,maxm=200010,maxt=maxn<<2;
    typedef long long ll;
    using namespace std;
    int n,Q,pre[maxm],now[maxn],son[maxm],tot,tim,last[maxn],w[maxn],tmp[maxn],dep[maxn],root=1,fa[maxn][22],pw[22];char op[12];
    void add(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
    void jump(int &a,int h){for (int i=18;h;i--) if (h&pw[i]) h-=pw[i],a=fa[a][i];}
    
    struct Tsegment_Tree{
    	#define ls (p<<1)
    	#define rs (p<<1|1)
    	#define mid ((l+r)>>1)
    	ll sum[maxt];int add[maxt],siz[maxt];
    	inline void update(int p){sum[p]=sum[ls]+sum[rs];}
    	inline void inc(int p,int v){sum[p]+=1ll*v*siz[p],add[p]+=v;}
    	inline void down(int p){if (add[p]) inc(ls,add[p]),inc(rs,add[p]),add[p]=0;}
    	void build(int p,int l,int r){
    		if (l==r){sum[p]=tmp[l],siz[p]=1;return;}
    		build(ls,l,mid),build(rs,mid+1,r);
    		update(p),siz[p]=siz[ls]+siz[rs];
    	}
    	void modify(int p,int l,int r,int a,int b,int v){
    		if (a>b) return;
    		if (l==a&&r==b){inc(p,v);return;}
    		down(p);
    		if (b<=mid) modify(ls,l,mid,a,b,v);
    		else if (a>mid) modify(rs,mid+1,r,a,b,v);
    		else modify(ls,l,mid,a,mid,v),modify(rs,mid+1,r,mid+1,b,v);
    		update(p);
    	}
    	ll query(int p,int l,int r,int a,int b){
    		if (a>b) return 0;
    		if (l==a&&r==b) return sum[p];
    		down(p);
    		if (b<=mid) return query(ls,l,mid,a,b);
    		else if (a>mid) return query(rs,mid+1,r,a,b);
    		else return query(ls,l,mid,a,mid)+query(rs,mid+1,r,mid+1,b);
    	}
    	void modify(int x,int v){
    		if (x==root) modify(1,1,n,1,n,v);
    		else if (w[root]>w[x]&&w[root]<=last[x]){
    			int y=root;jump(y,dep[root]-dep[x]-1);
    			modify(1,1,n,1,w[y]-1,v),modify(1,1,n,last[y]+1,n,v);
    		}
    		else modify(1,1,n,w[x],last[x],v);
    	}
    	double query(int x){
    		if (x==root) return 1.0*query(1,1,n,1,n)/n;
    		else if (w[root]>w[x]&&w[root]<=last[x]){
    			int y=root;jump(y,dep[root]-dep[x]-1);
    			int sz=w[y]-1+n-last[y];
    			return 1.0*(query(1,1,n,1,w[y]-1)+query(1,1,n,last[y]+1,n))/sz;
    		}
    		else return 1.0*query(1,1,n,w[x],last[x])/(last[x]-w[x]+1);
    	}
    }T;
    
    struct Tlct{
    	#define lc ch[x][0]
    	#define rc ch[x][1]
    	int ch[maxn][2],fa[maxn],siz[maxn];bool rev[maxn];
    	inline int isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    	inline int which(int x){return ch[fa[x]][1]==x;}
    	inline void update(int x){siz[x]=siz[lc]+siz[rc]+1;}
    	inline void rever(int x){swap(lc,rc),rev[x]^=1;}
    	inline void down(int x){if (rev[x]) rever(lc),rever(rc),rev[x]=0;}
    	void relax(int x){if (!isroot(x)) relax(fa[x]);down(x);}
    	void rotate(int x){
    		int y=fa[x],z=fa[y],nx=which(x),ny=which(y);
    		fa[ch[x][!nx]]=y,ch[y][nx]=ch[x][!nx];
    		fa[x]=z;if (!isroot(y)) ch[z][ny]=x;
    		fa[y]=x,ch[x][!nx]=y;update(y);
    	}
    	void splay(int x){
    		for (relax(x);!isroot(x);){
    			int y=fa[x];
    			if (isroot(y)) rotate(x);
    			else if (which(x)==which(y)) rotate(y),rotate(x);
    			else rotate(x),rotate(x);
    		}
    		update(x);
    	}
    	int shallow(int x){
    		down(x);while (lc) x=lc,down(x);
    		return x;
    	}
    	void access(int x){
    		for (int y=0;x;y=x,x=fa[x]){
    			splay(x);
    			if (rc) T.modify(shallow(rc),1);
    			fa[rc=y]=x;
    			if (y) T.modify(shallow(y),-1);
    			update(x);
    		}
    	}
    	void makeroot(int x){access(x),splay(x),rever(x),root=x;}
    }lct;
    
    void dfs(int x){
    	lct.fa[x]=fa[x][0],w[x]=++tim,tmp[tim]=tmp[w[fa[x][0]]]+1;
    	for (int i=1;i<=18;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    	for (int y=now[x];y;y=pre[y]) 
    		if (son[y]!=fa[x][0]) dep[son[y]]=dep[x]+1,fa[son[y]][0]=x,dfs(son[y]);
    	last[x]=tim;
    }
    
    int main(){
    	pw[0]=1;for (int i=1;i<=20;i++) pw[i]=pw[i-1]<<1;
    	scanf("%d%d",&n,&Q);
    	for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
    	tmp[1]=1,dfs(1),T.build(1,1,n);
    	for (int i=1,x;i<=Q;i++){
    		scanf("%s%d",op+1,&x);
    		if (op[3]=='L') lct.access(x);
    		else if (op[3]=='C') lct.makeroot(x);
    		else printf("%.10lf
    ",T.query(x));
    	}
    	return 0;
    }








  • 相关阅读:
    利用dockerfile定制镜像
    发布Docker 镜像到dockerhub
    Docker 停止容器
    133. Clone Graph
    132. Palindrome Partitioning II
    131. Palindrome Partitioning
    130. Surrounded Regions
    129. Sum Root to Leaf Numbers
    128. Longest Consecutive Sequence
    127. Word Ladder
  • 原文地址:https://www.cnblogs.com/thythy/p/5493450.html
Copyright © 2011-2022 走看看