BZOJ1180 OTOCI(LCT动态树)

Some time ago Mirko founded a new tourist agency named "Dreams of Ice". The agency purchased N icy islands near the South Pole and now offers excursions. Especially popular are the emperor penguins, which can be found in large numbers on the islands.

Mirko's agency has become a huge hit; so big that it is no longer cost-effective to use boats for the excursions. The agency will build bridges between islands and transport tourists by buses. Mirko wants to introduce a computer program to manage the bridge building process so that fewer mistakes are made.

The islands are numbered 1 through N. No two islands are initially connected by bridges. The initial number of penguins on each island is known. That number may change, but will always be between 0 and 1000 (inclusive).

Your program must handle the following three types of commands:

  • "bridge A B" – an offer was received to build a bridge between islands A and B (A and B will be different). To limit costs, your program must accept the offer only if there isn't already a way to get from one island to the other using previously built bridges. If the offer is accepted, the program should output "yes", after which the bridge is built. If the offer is rejected, the program should output "no".
  • "penguins A X" – the penguins on island A have been recounted and there are now X of them. This is an informative command and your program does not need to respond.
  • "excursion A B" – a group of tourists wants an excursion from island A to island B. If the excursion is possible (it is possible to get from island A to B), the program should output the total number of penguins the tourists would see on the excursion (including islands A and B). Otherwise, your program should output "impossible".

Input

The first line contains the integer N (1 ≤ N ≤ 30 000), the number of islands.

The second line contains N integers between 0 and 1000, the initial number of penguins on each of the islands.

The third line contains an integer Q (1 ≤ Q ≤ 300 000), the number of commands.

Q commands follow, each on its own line.

Output

Output the responses to commands "bridge" and "excursion", each on its own line.

Example

Input:
5
4 2 4 5 6
10
excursion 1 1
excursion 1 2
bridge 1 2
excursion 1 2
bridge 3 4
bridge 3 5
excursion 4 5
bridge 1 3
excursion 2 4
excursion 2 5

Output:
4
impossible
yes
6
yes
yes
15
yes
15
16


Input:
6
1 2 3 4 5 6
10
bridge 1 2
bridge 2 3
bridge 4 5
excursion 1 3
excursion 1 5
bridge 3 4
excursion 1 5
penguins 3 10
excursion 1 3
bridge 1 5

Output:
yes
yes
yes
6
impossible
yes
15
13
no

中文题意:


Description
给出n个结点以及每个点初始时对应的权值wi。起始时点与点之间没有连边。有3类操作: 1、bridge A B:询问结点A与结点B是否连通。如果是则输出“no”。否则输出“yes”,并且在结点A和结点B之间连一条无向边。 2、penguins A X:将结点A对应的权值wA修改为X。 3、excursion A B:如果结点A和结点B不连通,则输出“impossible”。否则输出结点A到结点B的路径上的点对应的权值的和。给出q个操作,要求在线处理所有操作。数据范围:1<=n<=30000, 1<=q<=300000, 0<=wi<=1000。

Input
第一行包含一个整数n(1<=n<=30000),表示节点的数目。第二行包含n个整数,第i个整数表示第i个节点初始时对应的权值。第三行包含一个整数q(1<=n<=300000),表示操作的数目。以下q行,每行包含一个操作,操作的类别见题目描述。任意时刻每个节点对应的权值都是1到1000的整数。

Output
输出所有bridge操作和excursion操作对应的输出,每个一行。

Sample Input
5
4 2 4 5 6
10
excursion 1 1
excursion 1 2
bridge 1 2
excursion 1 2
bridge 3 4
bridge 3 5
excursion 4 5
bridge 1 3
excursion 2 4
excursion 2 5

Sample Output
4
impossible
yes
6
yes
yes
15
yes
15
16

#include
#include
#include
#include
#include
#include
#define F(x) tree[x].fa
#define LC(x) tree[x].child[0]
#define RC(x) tree[x].child[1]
#define REV(x) tree[x].rev
#define Size 300010
using namespace std;
inline int read(){
	int sum=0,fg=1;char c=getchar();
	while(c<'0' || c>'9'){if(c=='-')fg=-1;c=getchar();}
	while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
	return sum*fg;
}
struct lct{
	int fa,child[2],rev,add;
	int v,sum;
}tree[Size];
struct link_cut_tree{
	inline bool isroot(int x){
		return LC(F(x))!=x && RC(F(x))!=x;
	}
	inline void pushup(int x){
		tree[x].sum=tree[LC(x)].sum+tree[RC(x)].sum+tree[x].v;
	}
	inline void pushdown(int x){
		if(REV(x)){
			REV(x)^=1;REV(LC(x))^=1;REV(RC(x))^=1;
			swap(LC(x),RC(x));
		}
	}
	void Pushdown(int x){
		if(!isroot(x))Pushdown(F(x));
		pushdown(x);
	}
	inline void rotate(int x){
		int A=F(x),B=F(A);bool w=(RC(A)==x);
		if(!isroot(A)){
			if(LC(B)==A)LC(B)=x;
			else if(RC(B)==A)RC(B)=x;
		}
		F(tree[x].child[w^1])=A;F(A)=x;F(x)=B;
		tree[A].child[w]=tree[x].child[w^1];tree[x].child[w^1]=A;
		pushup(A);pushup(x);
	}
	inline void splay(int x){
		Pushdown(x);
		while(!isroot(x)){
			if(!isroot(F(x)))rotate(x);
			rotate(x);
		}
	}
	inline void access(int x){
		for(int i=0;x;i=x,x=F(x))splay(x),RC(x)=i,pushup(x);
	}
	inline int find_root(int x){
		access(x);splay(x);
		while(LC(x))x=LC(x);
		return x;
	}
	inline void reverse(int x){
		access(x);splay(x);REV(x)^=1;
	}
	inline int link(int x,int y){
		if(find_root(x)==find_root(y))return 0;
		reverse(x);F(x)=y;return -1;
	}
	inline void cut(int x,int y){
		reverse(x);access(y);splay(y);
		F(LC(y))=0;LC(y)=0;pushup(y);
	}
	inline void update(int x,int val){
		splay(x);tree[x].v=val;pushup(x);
	}
	inline int query(int x,int y){
		if(find_root(x)!=find_root(y))return -1;
		reverse(x);access(y);splay(y);
		return tree[y].sum;
	}
}LCT;
int main(){
	int n=read();
	for(int i=1;i<=n;i++)
		tree[i].v=read();
	int m=read();
	char tp[10];
	while(m--){
		scanf("%s",tp);
		if(tp[0]=='b'){
			int x=read(),y=read();
			if(LCT.link(x,y)==-1)printf("yes\n");
			else printf("no\n");
		}
		else if(tp[0]=='p'){
			int x=read(),val=read();
			LCT.update(x,val);
		}
		else{
			int x=read(),y=read(),ans=LCT.query(x,y);
			if(ans==-1)printf("impossible\n");
			else printf("%d\n",ans);
		}
	}
	return 0;
}



你可能感兴趣的:(动态树——LCT)