BZOJ 2594 水管局长

Solution

由于链信息不好直接维护, 所以新建一个节点存储边的权值, 并把这个节点连向 它所连的节点 $u$, $v$

$pushup$中更新维护的 $mx$ 指向路径上权值最大的边的编号。

由于这题是只有删边, 没有添边, 所以可以离线倒序, 把删边变成添边。

Code

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define rd read()
  5 using namespace std;
  6 
  7 const int N = 1e6 + 5;
  8 
  9 int n, m, Q, ans[N];
 10 
 11 struct edge {
 12     int u, v, id, val, d;
 13 }e[N];
 14 
 15 struct que {
 16     int typ, u, v, id;
 17 }q[N];
 18 
 19 int read() {
 20     int X = 0, p = 1; char c = getchar();
 21     for (; c > '9' || c < '0'; c = getchar()) 
 22         if (c == '-') p = -1;
 23     for (; c >= '0' && c <= '9'; c = getchar())
 24         X = X * 10 + c - '0';
 25     return X * p;
 26 }
 27 
 28 namespace LCT {
 29     int ch[N][2], f[N], mx[N], tun[N], val[N];
 30     int st[N], tp;
 31 #define lc(x) ch[x][0]
 32 #define rc(x) ch[x][1]
 33 
 34     int isroot(int x) {
 35         return rc(f[x]) != x && 
 36         lc(f[x]) != x;
 37     }
 38 
 39     int get(int x) {
 40         return rc(f[x]) == x;
 41     }
 42 
 43     void rev(int x) {
 44         swap(lc(x), rc(x));
 45         tun[x] ^= 1;
 46     }
 47 
 48     void pushdown(int x) {
 49         if (tun[x]) {
 50             if (lc(x)) rev(lc(x));
 51             if (rc(x)) rev(rc(x));
 52             tun[x] = 0;
 53         }
 54     }
 55 
 56     void pd(int x) {
 57         while (!isroot(x)) {
 58             st[++tp] = x;
 59             x = f[x];
 60         }
 61         st[++tp] = x;
 62         while (tp) pushdown(st[tp--]);
 63     }
 64 
 65     void up(int x) {
 66         mx[x] = val[x];
 67         if (e[mx[lc(x)]].val > e[mx[x]].val) mx[x] = mx[lc(x)];
 68         if (e[mx[rc(x)]].val > e[mx[x]].val) mx[x] = mx[rc(x)];
 69     }
 70 
 71     void rotate(int x) {
 72         int old = f[x], oldf = f[old], son = ch[x][get(x) ^ 1];
 73         if (!isroot(old)) ch[oldf][get(old)] = x;
 74         ch[x][get(x) ^ 1] = old;
 75         ch[old][get(x)] = son;
 76         f[x] = oldf; f[old] = x; f[son] = old;
 77         up(old); up(x);
 78     }
 79 
 80     void splay(int x) {
 81         pd(x);
 82         for (; !isroot(x); rotate(x)) 
 83             if (!isroot(f[x]))
 84                 rotate(get(f[x]) == get(x) ? f[x] : x);
 85     }
 86 
 87     void access(int x) {
 88         for (int y = 0; x; y = x, x = f[x])
 89             splay(x), ch[x][1] = y, up(x);
 90     }
 91 
 92     void mroot(int x) {
 93         access(x); 
 94         splay(x); 
 95         rev(x);
 96     }
 97 
 98     void split(int x, int y) {
 99         mroot(x); 
100         access(y); 
101         splay(y);
102     }
103 
104     int findr(int x) {
105         access(x); splay(x);
106         while (lc(x)) pushdown(x), x = lc(x);
107         return x;
108     }
109 
110     void link(int x, int y) {
111         mroot(x); f[x] = y;
112     }
113 
114     void cut(int x, int y) {
115         split(x, y);
116         f[x] = ch[y][0] = 0;
117     }
118 }
119 using namespace LCT;
120 
121 int fd(int x, int y) {
122     int l = 1, r = m;
123     for (; l <= r;) {
124         int mid = (l + r) >> 1;
125         if (e[mid].u < x || (e[mid].u == x && e[mid].v < y))
126             l = mid + 1;
127         else if (e[mid].u == x && e[mid].v == y) return mid;
128         else r = mid - 1;
129     }
130     return 0;
131 }
132 
133 int cmp1(const edge &A, const edge &B) {
134     return A.val < B.val;
135 }
136 
137 int cmp2(const edge &A, const edge &B) {
138     return A.u == B.u ? A.v < B.v : A.u < B.u;
139 }
140 
141 int cmp3(const edge &A, const edge &B) {
142     return A.id < B.id;
143 }
144 
145 int main()
146 {
147     n = rd; m = rd; Q = rd;
148     for (int i = 1; i <= m; ++i) {
149         e[i].u = rd, e[i].v = rd, e[i].val = rd;
150         if (e[i].u > e[i].v)
151             swap(e[i].u, e[i].v);
152     }
153     sort(e + 1, e + 1 + m, cmp1);
154     for (int i = 1; i <= m; ++i) 
155         e[i].id = i, val[i + n] = i;
156     sort(e + 1, e + 1 + m, cmp2);
157     for (int i = 1; i <= Q; ++i) {
158         q[i].typ = rd;
159         q[i].u = rd;
160         q[i].v = rd;
161         if (q[i].u > q[i].v) 
162             swap(q[i].u, q[i].v);
163         if (q[i].typ == 2) {
164             int t = fd(q[i].u, q[i].v);
165             q[i].id = e[t].id;
166             e[t].d = 1;
167         }
168     }
169     sort(e + 1, e + 1 + m, cmp3);
170     for (int i = 1, tot = 0; i <= m; ++i) if (!e[i].d) {
171         int x = e[i].u, y = e[i].v;
172         mroot(x);
173         if (findr(y) != x) {
174             link(x, i + n);
175             link(y, i + n);
176             tot++;
177         }
178         if (tot == n - 1) break;
179     }
180     for (int i = Q; i; i--) {
181         if (q[i].typ == 1) {
182             split(q[i].u, q[i].v);
183             ans[i] = e[mx[q[i].v]].val;
184         }
185         else {
186             int x = q[i].u, y = q[i].v;
187             mroot(x);
188             if (findr(y) != x) {
189                 link(y, q[i].id + n);
190                 link(x, q[i].id + n);
191                 continue;
192             }
193             if (e[mx[y]].val > e[q[i].id].val) {
194                 int t = mx[y];
195                 cut(t + n, e[t].u);
196                 cut(t + n, e[t].v);
197                 link(q[i].id + n, x);
198                 link(q[i].id + n, y);
199             }
200         }
201     }
202     for (int i = 1; i <= Q; ++i)
203         if (q[i].typ == 1)
204             printf("%d
", ans[i]);
205 }
View Code
原文地址:https://www.cnblogs.com/cychester/p/9694655.html