BZOJ2843 极地旅行社 LCT
题意:初始时给定一个没有边的图,维护:1、添加一条边 2、修改单点权 3、询问u到v的点权和
题解:因为只有加边的操作,所以可以用LCT来维护,剩下的就是裸的操作了。
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int MAXN=30000+2; typedef struct NODE{ NODE *child[2],*f; int s,v; bool rev; NODE(){} NODE(NODE *_f):f(_f),rev(0){} } *TREE; TREE root,Null,mark[MAXN]; int N,M; char s[10+2]; TREE NewNode(TREE f){ TREE x=new NODE(f); x->child[0]=x->child[1]=Null; return x; } void Initialize(int N){ Null=NewNode(0); for(int i=1;i<=N;i++) mark[i]=NewNode(Null); } void Pushup(TREE &x){ x->s=x->child[0]->s+x->child[1]->s+x->v;} void Pushdown(TREE &x){ if(x->f->child[0]==x || x->f->child[1]==x) Pushdown(x->f); if(x->rev){ swap(x->child[0],x->child[1]); x->child[0]->rev^=1,x->child[1]->rev^=1; x->rev=0; } } void Rotate(TREE &x,bool t){ TREE y=x->f; y->child[!t]=x->child[t],x->child[t]->f=y,x->f=y->f; if(y->f->child[0]==y) y->f->child[0]=x; if(y->f->child[1]==y) y->f->child[1]=x; y->f=x,x->child[t]=y; Pushup(y),Pushup(x); } void Splay(TREE &x){ TREE y=x->f; Pushdown(x); while(y->child[1]==x || y->child[0]==x){ if(x==y->child[0]){ if(y==y->f->child[0]) Rotate(y,1); Rotate(x,1); } else{ if(y==y->f->child[1]) Rotate(y,0); Rotate(x,0); } y=x->f; } Pushup(x); } void Access(TREE &x){ TREE y=Null,z=x; while(z!=Null){ Splay(z); z->child[1]=y; Pushup(z); y=z,z=z->f; } } void Move(TREE &x){ Access(x),Splay(x); x->rev=1,Pushdown(x); } void Link(TREE &x,TREE &y){ Move(x); x->child[0]=Null,x->f=y; } TREE Find(TREE &x){ TREE y=x; while(y->f!=Null) y=y->f; return y; } void Update(TREE &x,int a){ Move(x),x->v=a,Pushup(x);} int Query(TREE &x,TREE &y){ Move(x),Access(y),Splay(y); Pushup(y); return y->s; } int main(){ scanf("%d",&N); Initialize(N); for(int i=1;i<=N;i++) scanf("%d",&mark[i]->s),mark[i]->v=mark[i]->s; scanf("%d",&M); for(int i=1,a,b;i<=M;i++){ scanf("%s %d %d",s,&a,&b); if(strstr(s,"bridge")) if(Find(mark[a])==Find(mark[b])) puts("no"); else Link(mark[a],mark[b]),puts("yes"); if(strstr(s,"penguins")) Update(mark[a],b); if(strstr(s,"excursion")) if(Find(mark[a])==Find(mark[b])) printf("%d\n",Query(mark[a],mark[b])); else puts("impossible"); } return 0; }