【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=2843
【题意】
给定一个森林,要求提供连边,修改点值,查询路径和的操作。
【思路】
LCT维护sum
对于一棵树LCT用splay维护该树的若干重路径,u->fa有三种:一种满足(u->fa->ch[0]==u||u->fa->ch[1]==u),即splay辅助树中的父亲;一种不满足上述要求,即辅助树(不同重路径)之间的连接;另一种u->fa==null,为原树的根。
查询两个节点是否连通即是否处于一棵原树,直接找到原树的根即可。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define FOR(a,b,c) for(int a=b;a<=c;a++) 5 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) 6 using namespace std; 7 8 typedef long long ll; 9 typedef unsigned int ul; 10 const int N = 4e5+10; 11 12 ll read() { 13 char c=getchar(); 14 ll f=1,x=0; 15 while(!isdigit(c)) { 16 if(c=='-') f=-1; c=getchar(); 17 } 18 while(isdigit(c)) 19 x=x*10+c-'0',c=getchar(); 20 return x*f; 21 } 22 23 namespace LCT { 24 25 struct Node { 26 Node *ch[2],*fa; 27 int rev,v,sum; 28 Node() ; 29 void reverse() { 30 rev^=1; 31 swap(ch[0],ch[1]); 32 } 33 void up_push() { 34 if(fa->ch[0]==this||fa->ch[1]==this) 35 fa->up_push(); 36 if(rev) { 37 ch[0]->reverse(); 38 ch[1]->reverse(); 39 rev=0; 40 } 41 } 42 void maintain() { 43 sum=ch[0]->sum+ch[1]->sum+v; 44 } 45 } *null=new Node,T[N]; 46 Node::Node() { 47 v=sum=rev=0; 48 fa=ch[0]=ch[1]=null; 49 } 50 51 void rot(Node* o,int d) { 52 Node *p=o->fa; 53 p->ch[d]=o->ch[d^1]; 54 o->ch[d^1]->fa=p; 55 o->ch[d^1]=p; 56 o->fa=p->fa; 57 if(p==p->fa->ch[0]) 58 p->fa->ch[0]=o; 59 else if(p==p->fa->ch[1]) 60 p->fa->ch[1]=o; 61 p->fa=o; 62 p->maintain(); 63 } 64 void splay(Node *o) { 65 o->up_push(); 66 Node *nf,*nff; 67 while(o->fa->ch[0]==o||o->fa->ch[1]==o) { 68 nf=o->fa,nff=nf->fa; 69 if(o==nf->ch[0]) { 70 if(nf==nff->ch[0]) rot(nf,0); 71 rot(o,0); 72 } else { 73 if(nf==nf->ch[1]) rot(nf,1); 74 rot(o,1); 75 } 76 } 77 o->maintain(); 78 } 79 void Access(Node* o) { 80 Node *son=null; 81 while(o!=null) { 82 splay(o); 83 o->ch[1]=son; 84 o->maintain(); 85 son=o; o=o->fa; 86 } 87 } 88 void evert(Node* o) { 89 Access(o); 90 splay(o); 91 o->reverse(); 92 } 93 void Link(Node* u,Node* v) { 94 evert(u); 95 u->fa=v; 96 } 97 void Cut(Node* u,Node* v) { 98 evert(u); 99 Access(v); splay(v); 100 u->fa=v->ch[0]=null; 101 v->maintain(); 102 } 103 Node* find(Node* o) { 104 while(o->fa!=null) o=o->fa; 105 return o; 106 } 107 } 108 using namespace LCT; 109 110 int n,q; 111 112 int main() 113 { 114 n=read(); 115 FOR(i,1,n) { 116 int x=read(); 117 T[i].sum=T[i].v=x; 118 } 119 q=read(); 120 char op[20]; 121 int u,v; 122 while(q--) { 123 scanf("%s",&op); 124 u=read(),v=read(); 125 if(op[0]=='b') { 126 if(find(&T[u])==find(&T[v])) puts("no"); 127 else { 128 puts("yes"); 129 Link(&T[u],&T[v]); 130 } 131 } else 132 if(op[0]=='p') { 133 evert(&T[u]); 134 T[u].v=v; 135 T[u].maintain(); 136 } else { 137 if(find(&T[u])!=find(&T[v])) puts("impossible"); 138 else { 139 evert(&T[u]); 140 Access(&T[v]); splay(&T[v]); 141 printf("%d ",T[v].sum); 142 } 143 } 144 } 145 return 0; 146 }