题目大意:给出一些初始相互分离的岛,有三个操作,1.分析两点是否联通,如果不连通,在之间连一条边。2.更改一个点的权值。3.询问两点之间路径上所有点的点权和。
思路:基本算是LCT的模板题了吧,好久没写了,基本都要忘了,这是照别人代码写的。。。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 30010
using namespace std;
struct SplayTree{
SplayTree *son[2],*father;
int val,sum;
bool reverse;
SplayTree(int _);
bool Check() {
return father->son[1] == this;
}
void Reverse() {
reverse ^= 1;
swap(son[0],son[1]);
}
void PushUp();
void PushDown();
}none(0),*nil = &none,*tree[MAX];
SplayTree:: SplayTree(int _) {
val = sum = _;
reverse = false;
son[0] = son[1] = father = nil;
}
void SplayTree:: PushDown() {
if(father->son[0] == this || father->son[1] == this)
father->PushDown();
if(reverse) {
son[0]->Reverse();
son[1]->Reverse();
reverse = false;
}
}
void SplayTree:: PushUp() {
sum = son[0]->sum + son[1]->sum + val;
}
int points,asks;
char s[20];
inline void Rotate(SplayTree *a,bool dir)
{
SplayTree *f = a->father;
f->son[!dir] = a->son[dir];
f->son[!dir]->father = f;
a->son[dir] = f;
a->father = f->father;
if(f->father->son[0] == f || f->father->son[1] == f)
f->father->son[f->Check()] = a;
f->father = a;
f->PushUp();
}
inline void Splay(SplayTree *a)
{
a->PushDown();
while(a->father->son[0] == a || a->father->son[1] == a) {
SplayTree *f = a->father;
if(f->father->son[0] != f && f->father->son[1] != f)
Rotate(a,!a->Check());
else if(!f->Check()) {
if(!a->Check())
Rotate(f,true),Rotate(a,true);
else Rotate(a,false),Rotate(a,true);
}
else {
if(a->Check())
Rotate(f,false),Rotate(a,false);
else Rotate(a,true),Rotate(a,false);
}
}
a->PushUp();
}
inline void Access(SplayTree *a)
{
SplayTree *temp = nil;
while(a != nil) {
Splay(a);
a->son[1] = temp;
a->PushUp();
temp = a;
a = a->father;
}
}
inline SplayTree *Find(SplayTree *a)
{
while(a->father != nil)
a = a->father;
return a;
}
inline void ToRoot(SplayTree *a)
{
Access(a);
Splay(a);
a->Reverse();
}
inline void Link(SplayTree *x,SplayTree *y)
{
ToRoot(x);
x->father = y;
}
int main()
{
cin >> points;
for(int x,i = 1; i <= points; ++i) {
scanf("%d",&x);
tree[i] = new SplayTree(x);
}
cin >> asks;
for(int x,y,i = 1; i <= asks; ++i) {
scanf("%s%d%d",s,&x,&y);
if(s[0] == 'b') {
SplayTree *fx = Find(tree[x]);
SplayTree *fy = Find(tree[y]);
if(fx == fy)
puts("no");
else {
puts("yes");
Link(tree[x],tree[y]);
}
}
else if(s[0] == 'p') {
Splay(tree[x]);
tree[x]->val = y;
tree[x]->PushUp();
}
else {
SplayTree *fx = Find(tree[x]);
SplayTree *fy = Find(tree[y]);
if(fx != fy)
puts("impossible");
else {
ToRoot(tree[x]);
Access(tree[y]);
Splay(tree[y]);
printf("%d\n",tree[y]->sum);
}
}
}
return 0;
}