BZOJ 2157: 旅游

2157: 旅游

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 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

3
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

3
2
1
-1
5
3

HINT

 

一共有10 个数据,对于第i (1 <= i <= 10) 个数据, N = M = i * 2000。

 

Source

 
[Submit][Status][Discuss]

 

 

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\n", tree[y].sum);
252         else if (s[1] == 'A')
253             makeRoot(tree + x), access(tree + y), printf("%d\n", tree[y].maxi);
254         else
255             makeRoot(tree + x), access(tree + y), printf("%d\n", tree[y].mini);
256     }
257 }

 

@Author: YouSiki

 

posted @ 2017-02-14 15:19  YouSiki  阅读(172)  评论(0编辑  收藏  举报