CF1416D Graph and Queries

https://www.luogu.com.cn/problem/CF1416D

妙妙套路题

首先可以把每条边的权值设为最后删除的时间,如果没被删则权值为 q + 1 q+1 q+1

建立kruskal重构树,这样就能保证同一颗子树里的可以互相到达

然后删边操作就变成了子树询问,删点操作就是单点修改

用线段树维护dfn序即可

code:

#include<bits/stdc++.h>
#define N 600050
#define M 500050
using namespace std;
int FA[N << 1];
int get(int x) {
    return x == FA[x]? x : (FA[x] = get(FA[x]));
}
vector<int> g[N];
void insert(int u, int v) { //printf("%d --> %d\n", u, v);
    g[u].push_back(v);
}
struct EE {
    int x, y, t;
} e[M << 1];
int cmp(EE x, EE y) {
    return x.t > y.t;
}
int tot, n, m, tim[N];
void kruskal() {
    tot = n;
    sort(e + 1, e + 1 + m, cmp);
    for(int i = 0; i <= 2 * n; i ++ ) FA[i] = i;
    for(int i = 1; i <= m; i ++) {
        int x = get(e[i].x), y = get(e[i].y);
        if(x == y) continue;
        tim[++ tot] = e[i].t;
        insert(tot, x);//, insert(x, tot);
        insert(tot, y);//, insert(y, tot);
        FA[x] = FA[y] = tot;
    }
}

int gs, dfn[N], size[N], fa[N][21], py[N];
void dfs(int u) {
    size[u] = 1;
    dfn[u] = ++ gs; py[gs] = u;
    for(int v : g[u]) {
        if(v == fa[u][0]) continue;
        fa[v][0] = u;
        dfs(v); size[u] += size[v];
    }
}

#define ls (rt << 1)
#define rs (rt << 1 | 1)
int ma[N << 3], a[N];
int update(int l, int r) {
    if(a[l] > a[r]) return l;
    else return r;
}
void build(int rt, int l, int r) {
    if(l == r) {
        ma[rt] = py[l];
        return ;
    }
    int mid = (l + r) >> 1;
    build(ls, l, mid), build(rs, mid + 1, r);
    ma[rt] = update(ma[ls], ma[rs]);
}
void clr(int rt, int l, int r, int x) {
    if(l == r) {
        a[py[l]] = 0;
        return ;
    }
    int mid = (l + r) >> 1;
    if(x <= mid) clr(ls, l, mid, x);
    else clr(rs, mid + 1, r, x);
    ma[rt] = update(ma[ls], ma[rs]);
}
int query(int rt, int l, int r, int L, int R) {
    if(L <= l && r <= R) return ma[rt];
    int mid = (l + r) >> 1, ret = 0;
    if(L <= mid) ret = update(ret, query(ls, l, mid, L, R));
    if(R > mid) ret = update(ret, query(rs, mid + 1, r, L, R));
    return ret;
}
int find(int x, int ti) {
    for(int i = 19; i >= 0; i --) if(fa[x][i] && tim[fa[x][i]] >= ti) x = fa[x][i];
    return x;
}
int qq, ans[M];
struct Q {
    int o, x;
} q[M << 1];
int main() {
    scanf("%d%d%d", &n, &m, &qq);
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);

    for(int i = 1; i <= n; i ++) tim[i] = qq + 1;
    for(int i = 1; i <= m; i ++) {
        scanf("%d%d", &e[i].x, &e[i].y);
        e[i].t = qq + 1;
    }
    for(int i = 1; i <= qq; i ++) {
        scanf("%d%d", &q[i].o, &q[i].x);
        if(q[i].o == 2) e[q[i].x].t = i;
    }

    //for(int i = 1; i <= m; i ++) printf("%d %d %d\n", e[i].x, e[i].y, e[i].t); printf("\n");
    kruskal();
    //for(int i = 1; i <= tot; i ++) printf("%d ", tim[i]); printf("\n");
    for(int i = 1; i <= tot; i ++) if(FA[i] == i) dfs(i);

    for(int j = 1; j <= 19; j ++)
        for(int i = 1; i <= tot; i ++) 
            fa[i][j] = fa[fa[i][j - 1]][j - 1]; 

    build(1, 1, tot);
    for(int i = 1; i <= qq; i ++) if(q[i].o == 1) {
        int x = find(q[i].x, i);
     //   printf("* %d %d  %d\n", i, q[i].x, x);
        x = query(1, 1, tot, dfn[x], dfn[x] + size[x] - 1);
        ans[i] = a[x];

        if(a[x]) clr(1, 1, tot, dfn[x]);
    }
    for(int i = 1; i <= qq; i ++) if(q[i].o == 1) printf("%d\n", ans[i]);
    return 0;
}
posted @ 2021-11-15 09:29  lahlah  阅读(30)  评论(0编辑  收藏  举报