BZOJ2843 极地旅行社 LCT
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ2843
题意概括
有n座岛
每座岛上的企鹅数量虽然会有所改变,但是始终在[0, 1000]之间。你的程序需要处理以下三种命令:
1."bridge A B"——在A与B之间建立一座大桥(A与B是不同的岛屿)。由于经费限制,这项命令被接受,当且仅当A与B不联通。若这项命令被接受,你的程序需要输出"yes",之后会建造这座大桥。否则,你的程序需要输"no"。
2."penguins A X"——根据可靠消息,岛屿A此时的帝企鹅数量变为X。这项命令只是用来提供信息的,你的程序不需要回应。
3."excursion A B"——一个旅行团希望从A出发到B。若A与B连通,你的程序需要输出这个旅行团一路上所能看到的帝企鹅数量(包括起点A与终点B),若不联通,你的程序需要输出"impossible"。
题解
本题仍然是LCT模版题。
bridge:先判断A和B是否联通,然后连边即可。
penguins:直接把A搞到付诸树根,然后修改就可以了。
excursion:先判断是否联通,然后如果不联通,那么我们走类似于cut的过程,让a成为b的左子节点且为最左子节点,那么答案就是size[a]+val[b]
代码
#include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=30005; int n,m; int fa[N],son[N][2],size[N],rev[N],val[N]; bool isroot(int x){ return son[fa[x]][0]!=x&&son[fa[x]][1]!=x; } void pushup(int x){ size[x]=val[x]+size[son[x][0]]+size[son[x][1]]; } void pushdown(int x){ if (rev[x]){ rev[x]=0; rev[son[x][0]]^=1; rev[son[x][1]]^=1; swap(son[x][0],son[x][1]); } } void pushadd(int x){ if (!isroot(x)) pushadd(fa[x]); pushdown(x); } int wson(int x){ return son[fa[x]][1]==x; } void rotate(int x){ if (isroot(x)) return; int y=fa[x],z=fa[y],L=wson(x),R=L^1; if (!isroot(y)) son[z][wson(y)]=x; fa[x]=z,fa[y]=x,fa[son[x][R]]=y; son[y][L]=son[x][R],son[x][R]=y; pushup(y); pushup(x); } void splay(int x){ pushadd(x); for (int y=fa[x];!isroot(x);rotate(x),y=fa[x]) if (!isroot(y)) rotate(wson(x)==wson(y)?y:x); } void access(int x){ int t=0; while (x){ splay(x); son[x][1]=t; pushup(x); t=x; x=fa[x]; } } void rever(int x){ access(x); splay(x); rev[x]^=1; } void link(int x,int y){ rever(x); fa[x]=y; } void cut(int x,int y){ rever(x); access(y); splay(y); fa[x]=son[y][0]=0; } int find(int x){ access(x); splay(x); while (1){ pushdown(x); if (son[x][0]) x=son[x][0]; else break; } return x; } int main(){ scanf("%d",&n); for (int i=1;i<=n;i++){ scanf("%d",&val[i]); size[i]=val[i],son[i][0]=son[i][1]=fa[i]=rev[i]=0; } scanf("%d",&m); while (m--){ char op[10]; int a,b; scanf("%s%d%d",op,&a,&b); if (op[0]=='b'){ if (find(a)==find(b)) puts("no"); else puts("yes"),link(a,b); } else if (op[0]=='p'){ rever(a); val[a]=b; pushup(a); } else { if (find(a)==find(b)){ rever(a); access(b); splay(b); printf("%d\n",size[son[b][0]]+val[b]); } else puts("impossible"); } } return 0; }