• Codeforces 1140F Extending Set of Points 线段树 + 按秩合并并查集 (看题解)


    Extending Set of Points

    我们能发现, 如果把x轴y轴看成点, 那么答案就是在各个连通块里面的x轴的个数乘以y轴的个数之和。

    然后就变成了一个并查集的问题, 但是这个题目里面有撤销的操作, 所以我们要把加入和撤销操作变成

    这个点影响(L , R)之间的询问, 然后把它丢到线段树里面分成log段, 然后我们dfs一遍线段树, 用按秩合并
    并查集取维护, 回溯的时候将并查集撤销。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ull unsigned long long
    
    using namespace std;
    
    const int N = 3e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 998244353;
    const double eps = 1e-6;
    const double PI = acos(-1);
    
    int n;
    LL ans[N];
    map<PII, int> Map;
    
    int fa[N << 1], cntx[N << 1], cnty[N << 1], sz[N << 1];
    LL now = 0;
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    vector<PII> vc[N << 2];
    void Insert(int L, int R, PII e, int l, int r, int rt) {
        if(l >= L && r <= R) {
            vc[rt].push_back(e);
            return;
        }
        int mid = l + r >> 1;
        if(L <= mid) Insert(L, R, e, lson);
        if(R >  mid) Insert(L, R, e, rson);
    }
    
    int getRoot(int x) {
        return fa[x] == x ? x : getRoot(fa[x]);
    }
    
    void Merge(int x, int y, stack<PII>& stk) {
        int fax = getRoot(x);
        int fay = getRoot(y);
        if(fax != fay) {
            if(sz[fax] < sz[fay]) swap(fax, fay);
            stk.push(mk(fax, fay));
            now -= 1ll * cntx[fax] * cnty[fax];
            now -= 1ll * cntx[fay] * cnty[fay];
            sz[fax] += sz[fay];
            cntx[fax] += cntx[fay];
            cnty[fax] += cnty[fay];
            fa[fay] = fax;
            now += 1ll * cntx[fax] * cnty[fax];
        }
    }
    
    void Delete(stack<PII>& stk) {
        while(!stk.empty()) {
            int fax = stk.top().fi;
            int fay = stk.top().se;
            stk.pop();
            now -= 1ll * cntx[fax] * cnty[fax];
            sz[fax] -= sz[fay];
            cntx[fax] -= cntx[fay];
            cnty[fax] -= cnty[fay];
            fa[fay] = fay;
            now += 1ll * cntx[fax] * cnty[fax];
            now += 1ll * cntx[fay] * cnty[fay];
        }
    }
    
    void dfs(int l, int r, int rt) {
        stack<PII> stk;
        for(auto& t : vc[rt]) Merge(t.fi, t.se, stk);
        if(l == r) ans[l] = now;
        else {
            int mid = l + r >> 1;
            dfs(l, mid, rt << 1);
            dfs(mid + 1, r, rt << 1 | 1);
        }
        Delete(stk);
    }
    
    int main() {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            PII e; scanf("%d%d", &e.fi, &e.se);
            e.se += 300000;
            if(Map.find(e) == Map.end()) {
                Map[e] = i;
            } else {
                Insert(Map[e], i - 1, e, 1, n, 1);
                Map.erase(e);
            }
        }
        for(auto& t : Map) Insert(t.se, n, t.fi, 1, n, 1);
        for(int i = 1; i <= 300000; i++) fa[i] = i, cntx[i] = 1, sz[i] = 1;
        for(int i = 300001; i <= 600000; i++) fa[i] = i, cnty[i] = 1, sz[i] = 1;
        dfs(1, n, 1);
        for(int i = 1; i <= n; i++) printf("%lld ", ans[i]);
        puts("");
        return 0;
     }
    
    /*
    */
  • 相关阅读:
    1042 Shuffling Machine
    1043 Is It a Binary Search Tree
    1044 Shopping in Mars
    1443. Minimum Time to Collect All Apples in a Tree
    1045 Favorite Color Stripe
    Java笔记八:Java内置的包装类(1)
    Java笔记七:Java数字和日期处理(2)
    Java笔记六:Java数字和日期处理(1)
    Java笔记五: Java正则表达式
    Java笔记四:Java字符串处理
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10606629.html
Copyright © 2020-2023  润新知