• 洛谷 P2147 [SDOI2008]洞穴勘测


    P2147 [SDOI2008]洞穴勘测
    思路:
    按时间分治,然后每条边有一个存活时间段,按存活时间段将边加入划分树,然后在划分树上分治,用可撤销并查集维护连通性。
    代码:

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize(4)
    #include<bits/stdc++.h>
    using namespace std;
    #define y1 y11
    #define fi first
    #define se second
    #define pi acos(-1.0)
    #define LL long long
    //#define mp make_pair
    #define pb push_back
    #define ls rt<<1, l, m
    #define rs rt<<1|1, m+1, r
    #define ULL unsigned LL
    #define pll pair<LL, LL>
    #define pli pair<LL, int>
    #define pii pair<int, int>
    #define piii pair<pii, int>
    #define pdd pair<double, double>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define debug(x) cerr << #x << " = " << x << "
    ";
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    //head
    
    const int N = 1e4 + 10, M = 2e5 + 5;
    vector<pii> vc[M<<2];
    int n, m, u[M], v[M], op[M];
    struct UFS {
        stack<pair<int*, int>> stk;
        int fa[N], rnk[N];
        inline void init(int n) {
            for (int i = 0; i <= n; ++i) fa[i] = i, rnk[i] = 0;
        }
        inline int Find(int x) {
            while(x^fa[x]) x = fa[x];
            return x;
        }
        inline void Merge(int x, int y) {
            x = Find(x), y = Find(y);
            if(x == y) return ;
            if(rnk[x] <= rnk[y]) {
                stk.push({fa+x, fa[x]});
                fa[x] = y;
                if(rnk[x] == rnk[y]) {
                    stk.push({rnk+y, rnk[y]});
                    rnk[y]++;
                }
            }
            else {
                stk.push({fa+y, fa[y]});
                fa[y] = x;
            }
        }
        inline void Undo() {
            *stk.top().fi = stk.top().se;
            stk.pop();
        }
    }ufs;
    void update(int L, int R, pii p, int rt, int l, int r) {
        if(L <= l && r <= R) return vc[rt].pb(p), void();
        int m = l+r >> 1;
        if(L <= m) update(L, R, p, ls);
        if(R > m) update(L, R, p, rs);
    }
    void dfs(int rt, int l, int r) {
        for (pii p : vc[rt]) ufs.Merge(p.fi, p.se);
        if(l == r){
            if(op[l] == 2) {
                if(ufs.Find(u[l]) == ufs.Find(v[l])) printf("Yes
    ");
                else printf("No
    ");
            }
            return ;
        }
        int m = l+r >> 1;
        int sz = ufs.stk.size();
        dfs(ls);
        while(ufs.stk.size() > sz) ufs.Undo();
        dfs(rs);
        while(ufs.stk.size() > sz) ufs.Undo();
    }
    char s[15];
    map<pii, int> mp;
    int main() {
        scanf("%d %d", &n, &m);
        ufs.init(n);
        for (int i = 1; i <= m; ++i) {
            scanf("%s", s);
            scanf("%d %d", &u[i], &v[i]);
            if(u[i] > v[i]) swap(u[i], v[i]);
            if(s[0] == 'C') op[i] = 0;
            else if(s[0] == 'D') op[i] = 1;
            else op[i] = 2;
            if(!op[i]) mp[{u[i], v[i]}] = i;
            else if(op[i] == 1) {
                update(mp[{u[i], v[i]}], i-1, {u[i], v[i]}, 1, 1, m);
                mp[{u[i], v[i]}] = 0;
            }
        }
    
        for (auto it : mp) if(it.se) update(it.se, m, it.fi, 1, 1, m);
        dfs(1, 1, m);
        return 0;
    }
    
  • 相关阅读:
    layui 标签页切换
    m1配置多个git账户
    sqlserver 获取表和字段的注释方法
    springboot+mybatisPlus 配置多数据源--转载
    nginx 配置静态网页和反向代理
    ORA-01000: maximum open cursors exceeded
    重装系统我们选择FAT还是NTFS?U盘和硬盘格式化两者选谁?
    2、条件表达式
    1、javascript 知识拓展
    1_maven 问题
  • 原文地址:https://www.cnblogs.com/widsom/p/11335528.html
Copyright © 2020-2023  润新知