BZOJ 3531 [Sdoi2014]旅行

题解:

解法1:

树链剖分一下,对每条链建立一颗Splay

以宗教为第一关键字,深度为第二关键字建立

查询相当于Splay的一个区间

修改相当于删除一个节点,加入一个节点

O(nlog^2n) O(n);

解法2:

树链剖分一下,对每条链建立maxc棵权值线段树,动态开点

O(nlog^2n) O(nlogn)

问题:自己还没写过动态开点线段树

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=300009;
const int inf=1000000000;
inline int max(int a,int b){
	if(a>b)return a;
	else return b;
}

int n,m;
int w[maxn],c[maxn];

int father[maxn],depth[maxn],siz[maxn];
int idp[maxn],rt[maxn],ref[maxn],hson[maxn],tp[maxn];

int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	head[x]=cntedge;
}

int nn;
int fa[maxn],ch[maxn][2],sum[maxn],mx[maxn];
inline void pushup(int x){
	sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+w[x];
	mx[x]=max(w[x],max(mx[ch[x][0]],mx[ch[x][1]]));
}
inline int son(int x){
	if(ch[fa[x]][1]==x)return 1;
	else return 0;
}

inline void Rotate(int &root,int x){
	int y=fa[x];
	int z=fa[y];
	int b=son(x),c=son(y);
	int a=ch[x][b^1];
	if(z)ch[z][c]=x;
	else root=x;
	fa[x]=z;
	if(a)fa[a]=y;
	ch[y][b]=a;
	fa[y]=x;ch[x][b^1]=y;
	pushup(y);pushup(x);
}
void Splay(int &root,int x,int i){
	while(fa[x]!=i){
		int y=fa[x];
		int z=fa[y];
		if(z==i){
			Rotate(root,x);
		}else{
			if(son(x)==son(y)){
				Rotate(root,y);Rotate(root,x);
			}else{
				Rotate(root,x);Rotate(root,x);
			}
		}
	}
}

inline int cmp(int x,int y){
	if(c[x]<c[y])return -1;
	if(c[x]>c[y])return 1;
	if(depth[x]<depth[y])return -1;
	if(depth[x]>depth[y])return 1;
	return 0;
}
	

void Ins(int &root,int p){
	int x=root,y=0;
	while(x){
		y=x;
		if(cmp(x,p)>0)x=ch[x][0];
		else x=ch[x][1];
	}
	x=p;
	fa[x]=y;ch[x][0]=ch[x][1]=0;
	sum[x]=mx[x]=w[x];
	if(y){
		if(cmp(x,y)<0)ch[y][0]=x;
		else ch[y][1]=x;
	}else{
		root=x;
	}
	Splay(root,x,0);
}

void Del(int &root,int x){
	Splay(root,x,0);
	if(ch[x][0]==0){
		root=ch[x][1];fa[ch[x][1]]=0;
	}else if(ch[x][1]==0){
		root=ch[x][0];fa[ch[x][0]]=0;
	}else{
		int p=ch[x][0];
		while(ch[p][1])p=ch[p][1];
		Splay(root,p,x);
		ch[p][1]=ch[x][1];fa[ch[x][1]]=p;
		root=p;fa[p]=0;pushup(p);
	}
}

void check(int x){
	if(ch[x][0])check(ch[x][0]);
	cout<<c[x]<<' '<<depth[x]<<endl;
	if(ch[x][1])check(ch[x][1]);
}

int Getpre(int root,int p){
	int x=root,ret=0;
	while(x){
		if(cmp(x,p)<0){
			ret=x;
			x=ch[x][1];
		}else{
			x=ch[x][0];
		}
	}
	return ret;
}
int Getsuf(int root,int p){
	int x=root,ret=0;
	while(x){
		if(cmp(x,p)>0){
			ret=x;
			x=ch[x][0];
		}else{
			x=ch[x][1];
		}
	}
	return ret;
}

void Dfs(int now,int ff){
	father[now]=ff;
	depth[now]=depth[ff]+1;
	siz[now]=1;
	for(int i=head[now];i;i=nex[i]){
		if(to[i]==ff)continue;
		Dfs(to[i],now);
		siz[now]+=siz[to[i]];
		if(siz[to[i]]>siz[hson[now]])hson[now]=to[i];
	}
}

int dfsclock;
void Dfs2(int now,int toppoint){
	idp[now]=++dfsclock;
	ref[dfsclock]=now;
	tp[now]=toppoint;
	Ins(rt[toppoint],now);
	if(!hson[now])return;
	Dfs2(hson[now],toppoint);
	for(int i=head[now];i;i=nex[i]){
		if(to[i]==father[now])continue;
		if(to[i]==hson[now])continue;
		Dfs2(to[i],to[i]);
	}
}

void ChangeC(int x,int y){
	Del(rt[tp[x]],x);
	c[x]=y;
	Ins(rt[tp[x]],x);
}
void ChangeW(int x,int y){
	Splay(rt[tp[x]],x,0);
	w[x]=y;pushup(x);
}

int QueryM(int u,int v){
	int tu=tp[u];
	int tv=tp[v];
	int ret=0;
	c[nn]=c[u];
	while(tu!=tv){
		if(depth[tu]<depth[tv]){
			swap(tu,tv);swap(u,v);
		}
		depth[nn]=depth[u];
		int p=Getsuf(rt[tu],nn);
		Splay(rt[tu],p,0);
		
		depth[nn]=depth[tu];
		p=Getpre(rt[tu],nn);
		Splay(rt[tu],p,rt[tu]);
		ret=max(ret,mx[ch[ch[rt[tu]][0]][1]]);
		
		u=father[tu];tu=tp[u];
	}
	if(depth[u]>depth[v])swap(u,v);
	depth[nn]=depth[v];
	int p=Getsuf(rt[tp[u]],nn);
	Splay(rt[tp[u]],p,0);
	
	depth[nn]=depth[u];
	p=Getpre(rt[tp[u]],nn);
	Splay(rt[tp[u]],p,rt[tp[u]]);
	ret=max(ret,mx[ch[ch[rt[tp[u]]][0]][1]]);
	return ret;
}

int QueryS(int u,int v){
	int tu=tp[u];
	int tv=tp[v];
	int ret=0;
	c[nn]=c[u];
	while(tu!=tv){
		if(depth[tu]<depth[tv]){
			swap(tu,tv);swap(u,v);
		}
		depth[nn]=depth[u];
		int p=Getsuf(rt[tu],nn);
		Splay(rt[tu],p,0);
		
		depth[nn]=depth[tu];
		p=Getpre(rt[tu],nn);
		Splay(rt[tu],p,rt[tu]);
		ret+=sum[ch[ch[rt[tu]][0]][1]];
		
		u=father[tu];tu=tp[u];
	}
	if(depth[u]>depth[v])swap(u,v);
	depth[nn]=depth[v];
	int p=Getsuf(rt[tp[u]],nn);
	Splay(rt[tp[u]],p,0);
	
	depth[nn]=depth[u];
	p=Getpre(rt[tp[u]],nn);
	Splay(rt[tp[u]],p,rt[tp[u]]);
	ret+=sum[ch[ch[rt[tp[u]]][0]][1]];
	return ret;
}

int main(){
//	freopen("travel.in","r",stdin);
//	freopen("travel.out","w",stdout);
	
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)scanf("%d%d",&w[i],&c[i]);
	for(int i=1;i<=n-1;++i){
		int x,y;
		scanf("%d%d",&x,&y);
		Addedge(x,y);
		Addedge(y,x);
	}
	Dfs(1,0);
	Dfs2(1,1);
	
	nn=n;
	for(int i=1;i<=n;++i){
		if(tp[i]==i){
			c[++nn]=-inf;
			c[++nn]=inf;
			Ins(rt[i],nn-1);
			Ins(rt[i],nn);
		}
	}
	++nn;
	
	while(m--){
		char opty[3];
		int x,y;
		scanf("%s",opty);
		scanf("%d%d",&x,&y);
		if(opty[1]=='C'){
			ChangeC(x,y);
		}
		if(opty[1]=='W'){
			ChangeW(x,y);
		}
		if(opty[1]=='M'){
			printf("%d\n",QueryM(x,y));
		}
		if(opty[1]=='S'){
			printf("%d\n",QueryS(x,y));
		}
	}
	return 0;
}

  

posted @ 2018-02-20 18:00  ws_zzy  阅读(130)  评论(0编辑  收藏  举报