BZOJ2843 极地旅行社 LCT

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ2843


题意概括

  有n座岛
  每座岛上的企鹅数量虽然会有所改变,但是始终在[0, 1000]之间。你的程序需要处理以下三种命令:
  1."bridge A B"——在A与B之间建立一座大桥(A与B是不同的岛屿)。由于经费限制,这项命令被接受,当且仅当A与B不联通。若这项命令被接受,你的程序需要输出"yes",之后会建造这座大桥。否则,你的程序需要输"no"。
  2."penguins A X"——根据可靠消息,岛屿A此时的帝企鹅数量变为X。这项命令只是用来提供信息的,你的程序不需要回应。
  3."excursion A B"——一个旅行团希望从A出发到B。若A与B连通,你的程序需要输出这个旅行团一路上所能看到的帝企鹅数量(包括起点A与终点B),若不联通,你的程序需要输出"impossible"。

题解

  本题仍然是LCT模版题。

  bridge:先判断A和B是否联通,然后连边即可。

  penguins:直接把A搞到付诸树根,然后修改就可以了。

  excursion:先判断是否联通,然后如果不联通,那么我们走类似于cut的过程,让a成为b的左子节点且为最左子节点,那么答案就是size[a]+val[b]


代码

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=30005;
int n,m;
int fa[N],son[N][2],size[N],rev[N],val[N];
bool isroot(int x){
	return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}
void pushup(int x){
	size[x]=val[x]+size[son[x][0]]+size[son[x][1]];
}
void pushdown(int x){
	if (rev[x]){
		rev[x]=0;
		rev[son[x][0]]^=1;
		rev[son[x][1]]^=1;
		swap(son[x][0],son[x][1]);
	}
}
void pushadd(int x){
	if (!isroot(x))
		pushadd(fa[x]);
	pushdown(x);
}
int wson(int x){
	return son[fa[x]][1]==x;
}
void rotate(int x){
	if (isroot(x))
		return;
	int y=fa[x],z=fa[y],L=wson(x),R=L^1;
	if (!isroot(y))
		son[z][wson(y)]=x;
	fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
	son[y][L]=son[x][R],son[x][R]=y;
	pushup(y);
	pushup(x);
}
void splay(int x){
	pushadd(x);
	for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
		if (!isroot(y))
			rotate(wson(x)==wson(y)?y:x);
}
void access(int x){
	int t=0;
	while (x){
		splay(x);
		son[x][1]=t;
		pushup(x);
		t=x;
		x=fa[x];
	}
}
void rever(int x){
	access(x);
	splay(x);
	rev[x]^=1;
}
void link(int x,int y){
	rever(x);
	fa[x]=y;
}
void cut(int x,int y){
	rever(x);
	access(y);
	splay(y);
	fa[x]=son[y][0]=0;
}
int find(int x){
	access(x);
	splay(x);
	while (1){
		pushdown(x);
		if (son[x][0])
			x=son[x][0];
		else
			break;
	}
	return x;
}
int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;i++){
		scanf("%d",&val[i]);
		size[i]=val[i],son[i][0]=son[i][1]=fa[i]=rev[i]=0;
	}
	scanf("%d",&m);
	while (m--){
		char op[10];
		int a,b;
		scanf("%s%d%d",op,&a,&b);
		if (op[0]=='b'){
			if (find(a)==find(b))
				puts("no");
			else
				puts("yes"),link(a,b);
		}
		else if (op[0]=='p'){
			rever(a);
			val[a]=b;
			pushup(a);
		}
		else {
			if (find(a)==find(b)){
				rever(a);
				access(b);
				splay(b);
				printf("%d\n",size[son[b][0]]+val[b]);
			}
			else
				puts("impossible");
		}
	}
	return 0;
}

  

posted @ 2017-12-13 15:25  zzd233  阅读(285)  评论(0编辑  收藏  举报