zoukankan      html  css  js  c++  java
  • CF571D Campus(191)

    题意

    \(n\)个点,维护两个森林,这里\(A,B\)两个森林对应的点都是一样的,相当于对两个森林操作都会影响这\(n\)个点
    开始森林里的树都是一个点,\(A,B\)支持合并(但树结构互不影响),\(A\)支持树赋\(0\)\(B\)支持树加值

    做法

    \(A,B\)分开做,每次合并新建一个虚点,这样相当于把\(n\)个点拍扁了,就比较好维护点集的操作

    求出对每次查询最近的一次赋\(0\)操作,然后再在这个区间里算\(B\)修改对该点的贡献
    将操作离线下来放在树上就可以做了

    有个小\(trick\)就是用树状数组倍增一下求最近的那次赋\(0\)操作

    Code(jly)

    #include <bits/stdc++.h>
    using namespace std;
    constexpr int N = 500000;
    struct Tree {
        int n;
        vector<int> parent, lc, rc, id;
        vector<vector<int>> mod;
        Tree(int n) {
            parent.assign(2 * n - 1, -1);
            lc.assign(2 * n - 1, -1);
            rc.assign(2 * n - 1, -1);
            id.resize(n);
            iota(id.begin(), id.end(), 0);
            mod.resize(2 * n - 1);
        }
    };
    long long fen[N + 1];
    void add(int x, int y) {
        for (int i = x + 1; i <= N; i += i & -i)
            fen[i] += y;
    }
    long long sum(int x) {
        long long res = 0;
        for (int i = x; i > 0; i -= i & -i)
            res += fen[i];
        return res;
    }
    long long sum(int l, int r) {return sum(r) - sum(l);}
    int getLeft(int x) {
        int s = sum(x);
        x = 0;
        for (int i = 1 << 18; i > 0; i /= 2) {
            if (x + i <= N && fen[x + i] < s) {
                x += i;
                s -= fen[x];
            }
        }
        return x;
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, m;
        cin >> n >> m;
        Tree t1(n), t2(n);
        vector<vector<int>> query(n);
        vector<int> lb(m), sz(2 * n - 1, 1);
        vector<long long> ans(m, -1);
        int c1 = 0, c2 = 0;
        for (int i = 0; i < m; ++i) {
            char op;
            cin >> op;
            if (op == 'U') {
                int a, b;
                cin >> a >> b;
                --a;
                --b;
                int p = n + (c1++);
                t1.parent[t1.id[a]] = t1.parent[t1.id[b]] = p;
                t1.lc[p] = t1.id[a];
                t1.rc[p] = t1.id[b];
                t1.id[a] = p;
                sz[p] = sz[t1.lc[p]] + sz[t1.rc[p]];
            } else if (op == 'M') {
                int a, b;
                cin >> a >> b;
                --a;
                --b;
                int p = n + (c2++);
                t2.parent[t2.id[a]] = t2.parent[t2.id[b]] = p;
                t2.lc[p] = t2.id[a];
                t2.rc[p] = t2.id[b];
                t2.id[a] = p;
            } else if (op == 'A') {
                int x;
                cin >> x;
                --x;
                t1.mod[t1.id[x]].push_back(i);
            } else if (op == 'Z') {
                int x;
                cin >> x;
                --x;
                t2.mod[t2.id[x]].push_back(i);
            } else {
                int x;
                cin >> x;
                --x;
                query[x].push_back(i);
            }
        }
        function<void(int)> dfs1 = [&](int u) {
            for (int i : t2.mod[u])
                add(i, 1);
            if (u < n) {
                for (int i : query[u])
                    lb[i] = getLeft(i);
            } else {
                dfs1(t2.lc[u]);
                dfs1(t2.rc[u]);
            }
            for (int i : t2.mod[u])
                add(i, -1);
        };
        function<void(int)> dfs2 = [&](int u) {
            for (int i : t1.mod[u])
                add(i, sz[u]);
            if (u < n) {
                for (int i : query[u])
                    ans[i] = sum(lb[i], i);
            } else {
                dfs2(t1.lc[u]);
                dfs2(t1.rc[u]);
            }
            for (int i : t1.mod[u])
                add(i, -sz[u]);
        };
        for (int i = 0; i < n + c2; ++i)
            if (t2.parent[i] == -1)
                dfs1(i);
        for (int i = 0; i < n + c1; ++i)
            if (t1.parent[i] == -1)
                dfs2(i);
        for (int i = 0; i < m; ++i)
            if (ans[i] != -1)
                cout << ans[i] << "\n";
        return 0;
    }
    
  • 相关阅读:
    hdu 5119 Happy Matt Friends
    hdu 5128 The E-pang Palace
    hdu 5131 Song Jiang's rank list
    hdu 5135 Little Zu Chongzhi's Triangles
    hdu 5137 How Many Maos Does the Guanxi Worth
    hdu 5122 K.Bro Sorting
    Human Gene Functions
    Palindrome(最长公共子序列)
    A Simple problem
    Alignment ( 最长上升(下降)子序列 )
  • 原文地址:https://www.cnblogs.com/Grice/p/12247775.html
Copyright © 2011-2022 走看看