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:
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 the responses to commands "bridge" and "excursion", each on its own line.
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;
}