Graph and Queries
Graph and Queries
一道比较套路的题,看到只有删边,容易想到可以倒过来做,将删边变成加边。但这样做后我们发现,难以处理询问后将\(p_u = 0\)。
我们想表示每个时刻哪些点是同一连通块,这是我们可以想到重构树,那么对于某一时刻,在同一连通块中的点一定是某棵子树内的点。这是我们可以用倍增求出\(v\)所在的子树的根结点。
接下来我们便要求子树内点权的最大值和修改点权,容易想到用\(dfs\)序将树转化成序列,那么问题就解决了。
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#define eb emplace_back
#define IN inline
using namespace std;
const int N = 5e5 + 5;
int a[N], dfn[N], w[N], dfc, cnt, tot, g[N][21], n, m, Q, fa[N], siz[N], vis[N];
vector<int> E[N];
IN int read() {
int t = 0,res = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) t |= (ch == '-');
for (; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ 48);
return t ? -res : res;
}
struct nd{int x, y, t;}b[N];
struct qy{int x, t;}c[N];
struct tree{int z, id;}f[N << 2];
void dfs(int u) {
dfn[u] = ++dfc, siz[u] = 1;
for (int i = 1; i <= 20; i++)
if (g[u][i - 1]) g[u][i] = g[g[u][i - 1]][i - 1]; else break;
for (auto v : E[u]) g[v][0] = u, dfs(v), siz[u] += siz[v];
}
int find(int x){return x ^ fa[x] ? fa[x] = find(fa[x]) : x;}
int gets(int x, int lit) {
for (int i = 20; i >= 0; i--)
if (g[x][i] && w[g[x][i]] > lit) x = g[x][i];
return x;
}
tree Max(tree x, tree y){return x.z > y.z ? x : y;}
void update(int l, int r, int k, int u, int v) {
if (l == r) return f[k] = tree{v, l}, void();
int mid = l + r >> 1;
if (u <= mid) update(l, mid, k << 1, u, v);
else update(mid + 1, r, k << 1 | 1, u, v);
f[k] = Max(f[k << 1], f[k << 1 | 1]);
}
tree query(int l, int r, int k, int L, int R) {
if (L <= l && r <= R) return f[k];
int mid = l + r >> 1; tree tmp = tree{0, 0};
if (L <= mid) tmp = query(l, mid, k << 1, L, R);
if (R > mid) tmp = Max(tmp, query(mid + 1, r, k << 1 | 1, L, R));
return tmp;
}
bool cmp(nd x, nd y){return x.t > y.t;}
int main() {
n = read(), m = read(), Q = read();
for (int i = 1; i <= n; i++) a[i] = read(), fa[i] = i;
for (int i = 1; i <= m; i++) b[i] = nd{read(), read(), Q + 1};
for (int i = 1; i <= Q; i++) {
int opt = read(), x = read();
if (opt == 1) c[++cnt] = qy{x, i};
else b[x].t = i;
}
sort(b + 1, b + 1 + m, cmp); int tot = n;
for (int i = 1; i <= m; i++) {
int t1 = find(b[i].x), t2 = find(b[i].y);
if (t1 == t2) continue;
w[++tot] = b[i].t, fa[t1] = fa[t2] = fa[tot] = tot;
E[tot].eb(t1), E[tot].eb(t2);
}
tot++, w[tot] = 0;
for (int i = 1; i <= n; i++)
if (!vis[find(i)]) E[tot].eb(find(i)), vis[find(i)] = 1;
dfs(tot);
for (int i = 1; i <= n; i++) update(1, tot, 1, dfn[i], a[i]);
for (int i = 1; i <= cnt; i++) {
int u = gets(c[i].x, c[i].t);
tree res = query(1, tot, 1, dfn[u], dfn[u] + siz[u] - 1);
printf("%d\n", res.z), update(1, tot, 1, res.id, 0);
}
}

浙公网安备 33010602011771号