2019 Nowcoder Multi-University Training Contest 4 E Explorer

 

线段树分治。

把size看成时间,相当于时间 $l$ 加入这条边,时间 $r+1$ 删除这条边。

注意把左右端点的关系。

#include <bits/stdc++.h>

const int N = 2e5 + 7;
int X[N], Y[N], top;

struct DSU {
    int fa[N], sz[N];
    int find(int x) {
        while (x != fa[x]) x = fa[x];
        return x;
    }
    void merge(int x, int y) {
        x = find(x), y = find(y);
        if (x == y) return;
        if (sz[x] > sz[y]) std::swap(x, y);
        sz[y] += sz[x]; fa[x] = y;
        X[++top] = x;
        Y[top] = y;
    }
    void undo(int last) {
        for (; top > last; top--) {
            sz[Y[top]] -= sz[X[top]];
            fa[X[top]] = X[top];
        }
    }
    void clear(int n) {
        for (int i = 0; i <= n; i++)
            fa[i] = i, sz[i] = 1;
    }
} dsu;

int a[N], cnt, n, m, ans;

struct Node {
    int u, v, x, y;
};

void solve(int l, int r, const std::vector<Node> &vec) {
    if (vec.empty()) return;
    int temp = top, mid = l + r >> 1;
    std::vector<Node> L, R;
    for (auto p: vec) {
        if (p.x <= l && p.y >= r) {
            dsu.merge(p.u, p.v);
        } else {
            if (p.x <= mid) L.push_back(p);
            if (p.y > mid) R.push_back(p);
        }
    }
    if (dsu.find(1) == dsu.find(n)) {
        /*if (l == 4) {
            for (int i = 1; i <= top; i++)
                printf("%d %d\n", X[i], Y[i]);
        }*/
        ans += a[r] - a[l - 1];
        dsu.undo(temp);
        return;
    }
    if (l == r) {
        dsu.undo(temp);
        return;
    }
    solve(l, mid, L);
    solve(mid + 1, r, R);
    dsu.undo(temp);
}

int main() {
    freopen("in.txt", "r", stdin);
    std::vector<Node> vec;
    scanf("%d%d", &n, &m);
    vec.resize(m);
    for (int i = 0; i < m; i++) {
        scanf("%d%d%d%d", &vec[i].u, &vec[i].v, &vec[i].x, &vec[i].y);
        a[cnt++] = vec[i].x - 1, a[cnt++] = vec[i].y;
    }
    a[cnt++] = 0;
    std::sort(a, a + cnt);
    cnt = std::unique(a, a + cnt) - a;
    for (int i = 0; i < m; i++) {
        vec[i].x = std::lower_bound(a, a + cnt, vec[i].x) - a;
        vec[i].y = std::lower_bound(a, a + cnt, vec[i].y) - a;
    }
    dsu.clear(n);
    solve(1, cnt - 1, vec);
    printf("%d\n", ans);
    return 0;
}
View Code

 

posted @ 2019-10-31 19:09  Mrzdtz220  阅读(162)  评论(0)    收藏  举报