【BZOJ1036】【LCT版】树的统计Count
Description
一 棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输 入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数 q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到 30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
Hint
【分析】
随便写了一个LCT的版本,比树链剖分慢...
现在发现LCT真是个好东西,好写又有用。
1 /* 2 唐代白居易 3 《白云泉》 4 天平山上白云泉,云自无心水自闲。 5 何必奔冲山下去,更添波浪向人间。 6 */ 7 #include <iostream> 8 #include <cstdio> 9 #include <algorithm> 10 #include <cstring> 11 #include <vector> 12 #include <utility> 13 #include <iomanip> 14 #include <string> 15 #include <cmath> 16 #include <queue> 17 #include <assert.h> 18 #include <map> 19 #include <ctime> 20 #include <cstdlib> 21 #include <stack> 22 #define LOCAL 23 const int INF = 0x7fffffff; 24 const int MAXN = 30000 + 10; 25 const int maxnode = 1000000; 26 const int maxm= 30000 * 2 + 10; 27 using namespace std; 28 29 struct Link_Cut_Tree{ 30 struct Node{ 31 int val, sum, Max;//用来debug 32 int delta; 33 Node *parent; 34 Node *ch[2]; 35 }node[MAXN], *cur, _null, *null; 36 Node *tmp[MAXN]; 37 38 bool is_root(Node* t){//判断是否是splay的根 39 if (t == null || (t->parent->ch[0] != t && t->parent->ch[1] != t)) return 1; 40 return 0; 41 } 42 //本来以为不要pushdown了,结果还是要 43 void pushdown(Node *t){ 44 if (t == null) return; 45 if (t->delta){ 46 t->delta = 0; 47 if (t->ch[0] != null) t->ch[0]->delta ^= 1; 48 if (t->ch[1] != null) t->ch[1]->delta ^= 1; 49 swap(t->ch[0], t->ch[1]); 50 } 51 } 52 //更新 53 void update(Node *t){ 54 if (t == null) return; 55 t->sum = t->val; 56 if (t->ch[0] != null) t->sum += t->ch[0]->sum; 57 if (t->ch[1] != null) t->sum += t->ch[1]->sum; 58 t->Max = max(t->val, max(t->ch[0]->Max, t->ch[1]->Max)); 59 return; 60 } 61 void init(){ 62 null = &_null; 63 _null.val = _null.sum = _null.Max = -INF; 64 _null.delta = 0; 65 _null.parent = _null.ch[0] = _null.ch[1] = null; 66 67 cur = node + 1; 68 } 69 Node* NEW(int val){ 70 cur->parent = cur->ch[0] = cur->ch[1] = null; 71 cur->val = cur->Max = cur->sum = val; 72 cur->delta = 0; 73 return cur++; 74 } 75 void rotate(Node *t, int d){ 76 if (is_root(t)) return; 77 Node *p = t->parent; 78 p->ch[d ^ 1] = t->ch[d]; 79 if (t->ch[d] != null) t->ch[d]->parent = p; 80 t->parent = p->parent; 81 if (p != null){ 82 if (p->parent->ch[0] == p) p->parent->ch[0] = t; 83 else if (p->parent->ch[1] == p) p->parent->ch[1] = t; 84 } 85 t->ch[d] = p; 86 p->parent = t; 87 update(t); 88 update(p);//真逗,什么都不要 89 } 90 //将t旋转到根 91 void splay(Node *t){ 92 //标记下传 93 int cnt = 1; 94 tmp[0] = t; 95 for (Node *y = t; !is_root(y); y = y->parent) tmp[cnt++] = y->parent; 96 while (cnt) pushdown(tmp[--cnt]); 97 98 while (!is_root(t)){ 99 Node *y = t->parent; 100 if (is_root(y)) rotate(t, (y->ch[0] == t)); 101 else { 102 int d = (y->parent->ch[0] == y); 103 if (y->ch[d] == t) rotate(t, d ^ 1); 104 else rotate(y, d); 105 rotate(t, d); 106 } 107 update(t); 108 } 109 update(t); 110 } 111 Node* access(Node *t){ 112 Node *p = null; 113 while (t != null){ 114 splay(t); 115 if (p != null) p->parent = t; 116 t->ch[1] = p; 117 update(t); 118 p = t; 119 t = t->parent; 120 } 121 return p; 122 } 123 //合并u,v所在的树 124 void merge(Node *u, Node *v){ 125 access(u); 126 splay(u); 127 u->delta = 1; 128 u->parent = v; 129 return; 130 } 131 void cut(Node *u, Node *v){ 132 access(u)->delta ^= 1; 133 //splay(u);//转到顶上就切断v就可以了 134 access(v); 135 splay(v); 136 137 v->ch[0]->parent = null; 138 v->ch[0] = null; 139 return; 140 } 141 //找根 142 Node *find(Node *t){ 143 access(t); 144 splay(t); 145 while (t->parent != null) t = t->parent; 146 return t; 147 } 148 bool check(Node *u, Node *v){ 149 while (u->parent != null) u = u->parent; 150 while (v->parent != null) v = v->parent; 151 return (u == v); 152 } 153 void change(Node *l, int x){ 154 access(l); 155 splay(l); 156 l->val = x; 157 update(l); 158 } 159 }splay; 160 int n, m; 161 int u[MAXN] , v[MAXN]; 162 163 void init(){ 164 splay.init(); 165 scanf("%d", &n); 166 for (int i = 1; i < n; i++) scanf("%d%d", &u[i], &v[i]); 167 for (int i = 1; i <= n; i++){ 168 int a; 169 scanf("%d", &a); 170 splay.NEW(a); 171 } 172 for (int i = 1; i < n; i++) 173 splay.merge(splay.node + u[i], splay.node + v[i]); 174 } 175 void work(){ 176 int m ; 177 scanf("%d", &m); 178 for (int i = 1; i <= m; i++){ 179 char str[10]; 180 scanf("%s", str); 181 if (str[0] == 'C'){ 182 int l, x; 183 scanf("%d%d", &l, &x);//将l的值改为x 184 splay.change(splay.node + l, x); 185 }else if (str[0] == 'Q'){ 186 int l, r; 187 scanf("%d%d", &l, &r); 188 if (str[1] == 'S'){ 189 splay.access(splay.node + l)->delta ^= 1;//换根 190 splay.access(splay.node + r); 191 Link_Cut_Tree::Node *p = splay.find(splay.node + r); 192 printf("%d\n", p->sum); 193 }else{//求最大值 194 splay.access(splay.node + l)->delta ^= 1;//换根 195 splay.access(splay.node + r); 196 Link_Cut_Tree::Node *p = splay.find(splay.node + r); 197 printf("%d\n", p->Max); 198 } 199 } 200 } 201 } 202 203 int main (){ 204 205 init(); 206 work(); 207 return 0; 208 }