题目
不久之前,Mirko 建立了一个旅行社,名叫“极地之梦”。这家旅行社在北极附近购买了 nn 座冰岛,并且提供观光服务。
当地最受欢迎的当然是帝企鹅了,这些小家伙经常成群结队的游走在各个冰岛之间。Mirko 的旅行社遭受一次重大打击,以至于观光游轮已经不划算了。旅行社将在冰岛之间建造大桥,并用观光巴士来运载游客。
Mirko 希望开发一个电脑程序来管理这些大桥的建造过程,以免有不可预料的错误发生。这些冰岛从1到N标号。一开始时这些岛屿没有大桥连接,并且所有岛上的帝企鹅数量都是知道的。每座岛上的企鹅数量虽然会有所改变,但是始终在 [0, 1000][0,1000] 之间。你的程序需要处理以下三种命令:
bridge u v:询问结点 uu 与结点 vv 是否连通。如果是则输出 no;否则输出 yes,并且在结点 uu 和结点 vv 之间连一条无向边。
penguins u x:将结点 uu 对应的权值 w_uw
u
修改为 xx。
excursion u v:如果结点 uu 和结点 vv 不连通,则输出 impossible。否则输出结点 uu 到结点 vv 的路径上的点对应的权值的和。
思路
就是LCT板子题,维护一下splay的点权和即可
代码
#include<bits/stdc++.h>
using namespace std;
int fa[N],ch[N][2],v[N],tot[N],n,q,A,B,tem;
bool lazy[N];
char cha[101];
bool son(int x){return ch[fa[x]][1]==x;}
bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void pushup(int x){tot[x]=tot[ch[x][0]]+tot[ch[x][1]]+v[x];}
void spread(int x)
{
if(!lazy[x])return;
tem=ch[x][0];
ch[x][0]=ch[x][1];
ch[x][1]=tem;
lazy[ch[x][0]]^=1;
lazy[ch[x][1]]^=1;
lazy[x]=0;
}
void rotate(int x){
if(!x||!fa[x]||isroot(x))return;
int faz=fa[x],fazz=fa[faz],g=son(x);
fa[x]=fazz;
if(!isroot(faz))ch[fazz][son(faz)]=x;
fa[ch[x][!g]]=faz;
ch[faz][g]=ch[x][!g];
fa[faz]=x;
ch[x][!g]=faz;
pushup(faz);
pushup(x);
}
void clean(int x){
if(!isroot(x))clean(fa[x]);
spread(x);
}
void splay(int node)
{
clean(node);
while(!isroot(node)){
if(!isroot(fa[node]))
if(son(fa[node])^son(node))rotate(node);
else rotate(fa[node]);
rotate(node);
}
pushup(node);
}
void access(int x){
for(int y=0;x;y=x,x=fa[x])
splay(x),ch[x][1]=y,pushup(x);
}
void mroot(int x){
access(x);
splay(x);
lazy[x]^=1;
}
void split(int x,int y){
mroot(x);
access(y);
splay(y);
}
void link(int x,int y){
mroot(x);
fa[x]=y;
}
int findroot(int x)
{
access(x);
splay(x);
while(ch[x][0])x=ch[x][0];
return x;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",v+i),tot[i]=v[i];
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%s%d%d",cha,&A,&B);
if(cha[0]=='b')
{
if(findroot(A)==findroot(B))puts("no");
else
{
puts("yes");
link(A,B);
}
}
else if(cha[0]=='p')access(A),splay(A),v[A]=B,pushup(A);
else if(cha[0]=='e')
{
if(findroot(A)!=findroot(B))
{
puts("impossible");
continue;
}
split(A,B);
printf("%d\n",tot[B]);
}
}
}
版权声明:本文为Eric1561759334原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。