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的路径上的点对应的权值的和。
数据范围:1<=n<=30000, 1<=q<=300000, 0<=wi<=1000。
Solution
非常naive的LCT裸题
做这个主要是想说明一个问题,link(x,y)的时候既可以在xy之间连一条虚边,也可以瞎jb操作然后连实边
LCT真是太神奇辣
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int N=600005;
struct treeNode {int son[2],fa,sum,v; bool rev,is_root;} t[N];
int fa[N];
void push_up(int x) {
t[x].sum=t[x].v;
if (t[x].son[0]) t[x].sum+=t[t[x].son[0]].sum;
if (t[x].son[1]) t[x].sum+=t[t[x].son[1]].sum;
}
void push_down(int x) {
if (!x||!t[x].rev) return ;
std:: swap(t[x].son[0],t[x].son[1]);
t[t[x].son[0]].rev^=1;
t[t[x].son[1]].rev^=1;
t[x].rev=0;
}
void remove(int x) {
if (!t[x].is_root) remove(t[x].fa);
push_down(x);
}
void rotate(int x) {
if (t[x].is_root) return ;
int y=t[x].fa; int z=t[y].fa;
int k=t[y].son[1]==x;
t[y].son[k]=t[x].son[!k];
if (t[x].son[!k]) t[t[x].son[!k]].fa=y;
t[x].son[!k]=y; t[y].fa=x;
t[x].fa=z;
if (t[y].is_root) {
t[x].is_root=1;
t[y].is_root=0;
} else t[z].son[t[z].son[1]==y]=x;
push_up(y); push_up(x);
}
void splay(int x) {
remove(x);
while (!t[x].is_root) {
int y=t[x].fa; int z=t[y].fa;
if (!t[y].is_root) {
if ((t[z].son[1]==y)^(t[y].son[1]==x)) rotate(x);
rotate(y);
}
rotate(x);
}
}
void access(int x) {
int y=0;
do {
splay(x);
t[t[x].son[1]].is_root=1;
t[t[x].son[1]=y].is_root=0;
push_up(x);
y=x; x=t[x].fa;
} while (x);
}
void mroot(int x) {
access(x); splay(x); t[x].rev^=1;
}
void link(int x,int y) {
//mroot(x); t[x].fa=y;
mroot(x); access(y); t[x].fa=y; t[y].son[1]=x;
t[x].is_root=0;
splay(x);
}
void cut(int x,int y) {
mroot(x); access(y); splay(y);
t[y].son[1]=t[x].fa=0;
t[x].is_root=1;
push_up(y);
}
int get_father(int x) {
if (!fa[x]) return x;
return fa[x]=get_father(fa[x]);
}
int main(void) {
int n; scanf("%d",&n);
rep(i,1,n) {
scanf("%d",&t[i].v);
t[i].sum=t[i].v;
t[i].is_root=1;
}
int m; scanf("%d",&m);
while (m--) {
char opt[11]; scanf("%s",opt);
int x,y; scanf("%d%d",&x,&y);
if (opt[0]=='b') {
if (get_father(x)==get_father(y)) puts("no");
else {
puts("yes");
link(x,y);
fa[get_father(x)]=get_father(y);
}
} else if (opt[0]=='p') {
mroot(x); t[x].v=y; push_up(x);
} else {
if (get_father(x)!=get_father(y)) {
puts("impossible");
continue;
} else {
mroot(x); access(y); splay(y);
printf("%d\n", t[y].sum);
}
}
}
return 0;
}