2157: 旅游
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1347 Solved: 619
[Submit][Status][Discuss]
Description
Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N − 1 座桥。Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。
Input
输入的第一行包含一个整数N,表示T 城中的景点个数。景点编号为 0...N − 1。接下来N − 1 行,每行三个整数u、v 和w,表示有一条u 到v,使 Ray 愉悦度增加w 的桥。桥的编号为1...N − 1。|w| <= 1000。输入的第N + 1 行包含一个整数M,表示Ray 的操作数目。接下来有M 行,每行描述了一个操作,操作有如下五种形式: C i w,表示Ray 对于经过第i 座桥的愉悦度变成了w。 N u v,表示Ray 对于经过景点u 到v 的路径上的每一座桥的愉悦度都变成原来的相反数。 SUM u v,表示询问从景点u 到v 所获得的总愉悦度。 MAX u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最大愉悦度。 MIN u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最小愉悦度。测试数据保证,任意时刻,Ray 对于经过每一座桥的愉悦度的绝对值小于等于1000。
Output
对于每一个询问(操作S、MAX 和MIN),输出答案。
Sample Input
0 1 1
1 2 2
8
SUM 0 2
MAX 0 2
N 0 1
SUM 0 2
MIN 0 2
C 1 3
SUM 0 2
MAX 0 2
Sample Output
2
1
-1
5
3
HINT
一共有10 个数据,对于第i (1 <= i <= 10) 个数据, N = M = i * 2000。
Source
Link-Cut-Tree 模板题
维护子树(路径)最值、权值和
1 #include <cstdio> 2 3 template <class T> 4 inline T swap(T &a, T &b) 5 { 6 T c; 7 c = a; 8 a = b; 9 b = c; 10 } 11 12 template <class T> 13 inline T max(const T &a, const T &b) 14 { 15 return a > b ? a : b; 16 } 17 18 template <class T> 19 inline T min(const T &a, const T &b) 20 { 21 return a < b ? a : b; 22 } 23 24 const int mxn = 50005; 25 const int inf = 1e9 + 9; 26 27 int n, m, val[mxn]; 28 29 struct node 30 { 31 int sum; 32 int maxi; 33 int mini; 34 bool neg; 35 bool rev; 36 node *son[2]; 37 node *father; 38 }tree[mxn]; 39 40 inline bool isRoot(node *t) 41 { 42 node *&f = t->father; 43 44 if (f == NULL)return true; 45 46 if (f->son[0] == t)return false; 47 if (f->son[1] == t)return false; 48 49 return true; 50 } 51 52 inline void addNeg(node *t) 53 { 54 t->neg ^= true; 55 56 swap(t->maxi, t->mini); 57 58 t->sum = -t->sum; 59 t->maxi = -t->maxi; 60 t->mini = -t->mini; 61 62 if (t - tree >= n) 63 { // edge 64 int id = t - tree - n; 65 66 val[id] = -val[id]; 67 } 68 } 69 70 inline void pushNeg(node *t) 71 { 72 if (t->neg) 73 { 74 t->neg = false; 75 76 if (t->son[0] != NULL)addNeg(t->son[0]); 77 if (t->son[1] != NULL)addNeg(t->son[1]); 78 } 79 } 80 81 inline void addRev(node *t) 82 { 83 t->rev ^= true; 84 85 swap(t->son[0], t->son[1]); 86 } 87 88 inline void pushRev(node *t) 89 { 90 if (t->rev) 91 { 92 t->rev = false; 93 94 if (t->son[0] != NULL)addRev(t->son[0]); 95 if (t->son[1] != NULL)addRev(t->son[1]); 96 } 97 } 98 99 inline void update(node *t) 100 { 101 if (t - tree < n) 102 { // point 103 t->sum = 0; 104 t->maxi = -inf; 105 t->mini = +inf; 106 } 107 else 108 { // edge 109 int id = t - tree - n; 110 111 t->sum = val[id]; 112 t->maxi = val[id]; 113 t->mini = val[id]; 114 } 115 116 if (t->son[0] != NULL) 117 { 118 t->sum += t->son[0]->sum; 119 t->maxi = max(t->maxi, t->son[0]->maxi); 120 t->mini = min(t->mini, t->son[0]->mini); 121 } 122 if (t->son[1] != NULL) 123 { 124 t->sum += t->son[1]->sum; 125 t->maxi = max(t->maxi, t->son[1]->maxi); 126 t->mini = min(t->mini, t->son[1]->mini); 127 } 128 } 129 130 inline void connect(node *t, node *f, bool k) 131 { 132 if (t != NULL)t->father = f; 133 if (f != NULL)f->son[k] = t; 134 } 135 136 inline void rotate(node *t) 137 { 138 node *f = t->father; 139 node *g = f->father; 140 141 bool s = f->son[1] == t; 142 143 connect(t->son[!s], f, s); 144 connect(f, t, !s); 145 146 t->father = g; 147 if (g && g->son[0] == f)g->son[0] = t; 148 if (g && g->son[1] == f)g->son[1] = t; 149 150 update(f); 151 update(t); 152 } 153 154 inline void pushdown(node *t) 155 { 156 pushNeg(t); 157 pushRev(t); 158 } 159 160 inline void pushDown(node *t) 161 { 162 static node *stk[mxn]; 163 164 int top = 0; 165 166 stk[++top] = t; 167 168 while (!isRoot(t)) 169 stk[++top] = t = t->father; 170 171 while (top)pushdown(stk[top--]); 172 } 173 174 inline void splay(node *t) 175 { 176 pushDown(t); 177 178 while (!isRoot(t)) 179 { 180 node *f = t->father; 181 node *g = f->father; 182 183 if (isRoot(f)) 184 rotate(t); 185 else 186 { 187 bool a = f && f->son[1] == t; 188 bool b = g && g->son[1] == f; 189 190 if (a == b) 191 rotate(f), rotate(t); 192 else 193 rotate(t), rotate(t); 194 } 195 } 196 } 197 198 inline void access(node *t) 199 { 200 node *q = t; 201 node *p = NULL; 202 203 while (t != NULL) 204 { 205 splay(t); 206 t->son[1] = p, update(t); 207 p = t, t = t->father; 208 } 209 210 splay(q); 211 } 212 213 inline void makeRoot(node *t) 214 { 215 access(t), addRev(t); 216 } 217 218 inline void link(node *t, node *f) 219 { 220 makeRoot(t), t->father = f; 221 } 222 223 signed main(void) 224 { 225 scanf("%d", &n); 226 227 for (int i = 1; i <= n; ++i) 228 update(tree + i); 229 for (int i = 1, x, y, w; i < n; ++i) 230 { 231 scanf("%d%d%d", &x, &y, &w); 232 val[i] = w, update(tree + i + n); 233 link(tree + x, tree + i + n); 234 link(tree + y, tree + i + n); 235 } 236 237 scanf("%d", &m); 238 239 while (m--) 240 { 241 static int x, y; 242 static char s[50]; 243 244 scanf("%s%d%d", s, &x, &y); 245 246 if (s[0] == 'C') 247 access(tree + x + n), val[x] = y, update(tree + x + n); 248 else if (s[0] == 'N') 249 makeRoot(tree + x), access(tree + y), addNeg(tree + y); 250 else if (s[0] == 'S') 251 makeRoot(tree + x), access(tree + y), printf("%d ", tree[y].sum); 252 else if (s[1] == 'A') 253 makeRoot(tree + x), access(tree + y), printf("%d ", tree[y].maxi); 254 else 255 makeRoot(tree + x), access(tree + y), printf("%d ", tree[y].mini); 256 } 257 }
@Author: YouSiki