BZOJ 4855 [Jsoi2016]轻重路径

题解:用树链剖分来维护树链剖分

令d[x]=size[heavyson[x]]-size[lightson[x]]

当d[x]<0时轻重儿子关系改变

用数据结构维护d[x]并找到这些位置改变即可

时间复杂度O(不会分析)

#include<iostream>
#include<cstdio>
#include<cstring>
#define lo now<<1
#define ro now<<1|1
using namespace std;
const int maxn=200009;

int n,m;

long long nowans=0;
int havein[maxn],root=0;
int del[maxn];

int ls[maxn],rs[maxn];
int father[maxn],siz[maxn],dep[maxn];
int idp[maxn],top[maxn],ref[maxn],hson[maxn];
void Dfs1(int now,int fa){
	father[now]=fa;
	dep[now]=dep[fa]+1;
	siz[now]=1;
	if(ls[now]){
		Dfs1(ls[now],now);
		siz[now]+=siz[ls[now]];
		if(siz[ls[now]]>siz[hson[now]])hson[now]=ls[now];
	}
	if(rs[now]){
		Dfs1(rs[now],now);
		siz[now]+=siz[rs[now]];
		if(siz[rs[now]]>siz[hson[now]])hson[now]=rs[now];
	}
}


int dfsclock=0;
void Dfs2(int now,int toppoint){
	if(now==toppoint)nowans-=now;
	
	idp[now]=++dfsclock;
	ref[dfsclock]=now;
	top[now]=toppoint;
	if(!hson[now])return;
	Dfs2(hson[now],toppoint);
	if((ls[now])&&(ls[now]!=hson[now]))Dfs2(ls[now],ls[now]);
	if((rs[now])&&(rs[now]!=hson[now]))Dfs2(rs[now],rs[now]);
}

struct SegmentTree{
	int l,r;
	int tag,mn;//siz[heavy[now]]-siz[light[son]]
	int havetop;//father[top[now]]
}tree[maxn<<2];
inline void pushup(int now){
	tree[now].mn=min(tree[lo].mn,tree[ro].mn);
	tree[now].havetop=(tree[lo].havetop|tree[ro].havetop);
}
inline void pushdown(int now){
	if(tree[now].tag){
		tree[lo].tag+=tree[now].tag;
		tree[ro].tag+=tree[now].tag;
		tree[lo].mn+=tree[now].tag;
		tree[ro].mn+=tree[now].tag;
		tree[now].tag=0;
	}
}

void BuildTree(int now,int l,int r){
	tree[now].l=l;tree[now].r=r;
	tree[now].tag=0;
	if(l==r){
		int x=ref[l];
		tree[now].mn=siz[hson[x]]-min(siz[ls[x]],siz[rs[x]]);
		tree[now].havetop=0;
		return;
	}
	int mid=(l+r)>>1;
	BuildTree(lo,l,mid);
	BuildTree(ro,mid+1,r);
	pushup(now);
}

void Updatasec(int now,int ll,int rr,int x){
	if(tree[now].l>=ll&&tree[now].r<=rr){
		tree[now].tag+=x;
		tree[now].mn+=x;
		return;
	}
	int mid=(tree[now].l+tree[now].r)>>1;
	pushdown(now);
	if(ll<=mid)Updatasec(lo,ll,rr,x);
	if(rr>mid)Updatasec(ro,ll,rr,x);
	pushup(now);
}

void Updatatop(int now,int ll,int rr,int x){
	if(ll>rr)return;
	if(tree[now].r<ll)return;
	if(tree[now].l>rr)return;
	if(tree[now].l==tree[now].r){
		tree[now].mn+=x;
		return;
	}
	pushdown(now);
	if(tree[lo].havetop)Updatatop(lo,ll,rr,x);
	if(tree[ro].havetop)Updatatop(ro,ll,rr,x);
	pushup(now);
}

void Changetop(int now,int ll,int rr){
	if(ll>rr)return;
	if(tree[now].r<ll)return;
	if(tree[now].l>rr)return;
	if(tree[now].l==tree[now].r){
		tree[now].mn=-tree[now].mn;
		tree[now].havetop=1;
		int x=ref[tree[now].l];
		if(ls[x]==hson[x]){
			nowans=nowans-ls[x]+rs[x];
			hson[x]=rs[x];
		}else{
			nowans=nowans-rs[x]+ls[x];
			hson[x]=ls[x];
		}
		return;
	}
	pushdown(now);
	if(tree[lo].mn<0)Changetop(lo,ll,rr);
	if(tree[ro].mn<0)Changetop(ro,ll,rr);
	pushup(now);
}

void Updatapoint(int now,int p,int x){
	if(tree[now].l==tree[now].r){
		tree[now].mn+=x;
		if(tree[now].mn<0){
			tree[now].mn=-tree[now].mn;
			tree[now].havetop=0;
			int o=ref[p];
			if(ls[o]==hson[o]){
				nowans=nowans-ls[o]+rs[o];
				hson[o]=rs[o];
			}else{
				nowans=nowans-rs[o]+ls[o];
				hson[o]=ls[o];
			}
		}
		return;
	}
	int mid=(tree[now].l+tree[now].r)>>1;
	pushdown(now);
	if(p<=mid)Updatapoint(lo,p,x);
	else Updatapoint(ro,p,x);
	pushup(now);
}

void ChangePath(int u){
	int x=u;
	while(x){
		int tx=top[x];
		Updatasec(1,idp[tx],idp[x],-1);
		
		Updatatop(1,idp[tx],idp[x]-1,2);
		Changetop(1,idp[tx],idp[x]-1);
//		x=tx;int fa=father[x];
//		if(!fa)break;
//		if(hson[fa]!=x){ 
//			Updatapoint(1,idp[fa],2);
//		}else{
//			Updatapoint(1,idp[fa],0);
//		}
		x=father[tx];tx=top[x];
	}
	x=u;
	while(x){
		x=top[x];
		int fa=father[x];
		if(!fa)break;
			if(hson[fa]!=x){ 
			Updatapoint(1,idp[fa],2);
		}else{
			Updatapoint(1,idp[fa],0);
		}
		x=fa;
	}
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d%d",&ls[i],&rs[i]);
		havein[ls[i]]++;
		havein[rs[i]]++;
	}
	for(int i=1;i<=n;++i)nowans+=i;
	for(int i=1;i<=n;++i)if(!havein[i])root=i;
	
	Dfs1(root,0);
	Dfs2(root,root);
	BuildTree(1,1,n);
	
	scanf("%d",&m);
	printf("%lld\n",nowans);
	del[0]=1;
	while(m--){
		int x;scanf("%d",&x);
		
		del[x]=1;
		ChangePath(x);
		if(ls[father[x]]==x){
			if(del[rs[father[x]]])nowans-=x;
		}else{
			if(del[ls[father[x]]])nowans-=x;
		}
		printf("%lld\n",nowans);
	}
	return 0;
}

  

posted @ 2018-03-11 21:47  ws_zzy  阅读(554)  评论(0编辑  收藏  举报