背景:
C
Q
O
I
CQOI
CQOI的大水题。
5
m
i
n
A
C
5minAC
5minAC,我才不会告诉你是
c
o
p
y
copy
copy模板改的 。
题目传送门:
https://www.luogu.org/problemnew/show/P4312
题意:
支持询问:两个点是否联通,两个点路径的权值和。
支持操作:加边。
思路:
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{int d,fa,sum,lazy,son[2];} tr[300010];
int n,m;
bool isroot(int x)
{
return tr[tr[x].fa].son[0]!=x&&tr[tr[x].fa].son[1]!=x;
}
bool isson(int x)
{
return x==tr[tr[x].fa].son[1];
}
void change(int x)
{
if(!x) return;
swap(tr[x].son[0],tr[x].son[1]);
tr[x].lazy^=1;
}
void pushup(int x)
{
tr[x].sum=tr[x].d+tr[tr[x].son[0]].sum+tr[tr[x].son[1]].sum;
}
void pushdown(int x)
{
if(!tr[x].lazy) return;
change(tr[x].son[0]),change(tr[x].son[1]);
tr[x].lazy=0;
}
void rot(int x)
{
int w=isson(x),y=tr[x].fa,yy=tr[y].fa;
tr[y].son[w]=tr[x].son[w^1];
if(tr[y].son[w]) tr[tr[y].son[w]].fa=y;
tr[x].fa=yy;
if(!isroot(y)) tr[yy].son[isson(y)]=x;
tr[x].son[w^1]=y;tr[y].fa=x;
pushup(y);
}
int sta[300010];
int top;
void splay(int x)
{
sta[top=1]=x;
for(int i=x;!isroot(i);i=tr[i].fa)
sta[++top]=tr[i].fa;
while(top) pushdown(sta[top--]);
for(int y=tr[x].fa;!isroot(x);rot(x),y=tr[x].fa)
if(!isroot(y)) isson(x)^isson(y)?rot(x):rot(y);
pushup(x);
}
void access(int x)
{
for(int y=0;x;y=x,x=tr[x].fa)
splay(x),tr[x].son[1]=y,pushup(x);
}
int findroot(int x)
{
access(x);splay(x);
while(tr[x].son[0]) x=tr[x].son[0];
//splay(x);
return x;
}
void makeroot(int x)
{
access(x);splay(x);change(x);
}
void link(int x,int y)
{
makeroot(x);
if(findroot(y)!=x) tr[x].fa=y;
}
void split(int x,int y)
{
makeroot(x);access(y);splay(y);
}
void del(int x,int y)
{
makeroot(x);
if(findroot(y)==x&&!tr[x].son[1]&&tr[x].fa==y) tr[x].fa=tr[y].son[0]=0,pushup(x),pushup(y);
}
int main()
{
char s[20];
int x,y;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
tr[i]=(node){x,0,0,0,{0,0}};
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s %d %d",s+1,&x,&y);
if(s[1]=='b')
{
if(findroot(x)!=findroot(y))
{
printf("yes\n");
link(x,y);
} else printf("no\n");
}
else if(s[1]=='p')
{
splay(x);
tr[x].d=y;
}
else if(s[1]=='e')
{
if(findroot(x)==findroot(y))
{
split(x,y);
printf("%d\n",tr[y].sum);
} else printf("impossible\n");
}
}
}