• 牛客练习赛38 离线 启发式合并并查集


    https://ac.nowcoder.com/acm/contest/358#question

    出题人有一个n个点,m条边的无向图,点有属性ai和bi,以及一个神秘常数kk
    有q组询问,每组询问给出正整数v,k和k个点
    对于每个询问,在原图中删去(给定的k个点所在的连通块)和(属性ai大于v的点)  (只作用于这次询问) 
    再删去与这些点相连的边(也只作用于这次询问)
    那么剩下的图就有了一些联通块
    对于每个联通块,定义其贡献为连通块中的不同的属性b数量(这个连通块中存在此属性b,且出现次数为kk的倍数)
    每个询问输出此时所有联通块的贡献的最大值
    题意

    首先可以发现,直接在线维护并不容易,所以考虑将v值排序离线处理。每一个询问前,只将比他v值小的点加入。

    维护联通块可以用并查集,难点在于联通块合并的时候联通块内合法颜色的种数不好维护,事实上可以用启发式合并的方法维护每个联通快内不同颜色的数量,然后用这样的方法维护联通块的最大值。

    由于每次询问还涉及到删除联通快的操作,所以不能只保存最大的答案,考虑用一个multiset维护所有联通块的答案,每次询问的时候将k个答案移除,询问完了再加入,由于k的总值范围确定,时间复杂度事实上也有保证。

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
    while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
    const double eps = 1e-9;
    const int maxn = 3e6 + 10;
    const int maxm = 3e6 + 10;
    const int maxq = 3e6 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,K;
    struct Node{
        int way;
        int v,x;
        Node(){}
        Node(int way,int v,int x):way(way),v(v),x(x){}
    }op[maxq + maxn];
    struct Edge{
        int to,next;
    }edge[maxm * 2];
    int head[maxn],tot;
    int ans[maxq],fa[maxn];
    vector<int>del[maxq];
    int vis[maxn],c[maxn],use[maxn];
    int num[maxn],size[maxn];
    map<int,int>color[maxn];
    bool cmp(Node a,Node b){
        if(a.v != b.v) return a.v < b.v;
        return a.way == 1;
    }
    multiset<int>P;
    void init(){
        for(int i = 0 ; i <= N; i ++){
            head[i] = -1;
            fa[i] = i;
            size[i] = 1;
        }
        tot = 0;
    }
    void add(int u,int v){
        edge[tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot++;
    }
    int find(int p){
        if(p == fa[p]) return p;
        return fa[p] = find(fa[p]);
    }
    void Union(int a,int b){
        a = find(a); b = find(b);
        if(a == b) return;
        if(size[a] > size[b]) swap(a,b);
        fa[a] = b;
        size[b] += size[a]; size[a] = 0;
        P.erase(P.find(num[a]));
        P.erase(P.find(num[b]));
        for(map<int,int>::iterator it = color[a].begin(); it != color[a].end(); it++){
            pair<int,int> x = *it;
            int &tmp = color[b][x.fi];
            if(tmp && !(tmp % K)){
                num[b]--;
            }
            tmp += x.second;
            if(tmp && !(tmp % K)){
                num[b]++;
            }
        }
        P.insert(num[b]); num[a] = 0;
    }
    map<int,int>Hash;
    int main(){
        Sca3(N,M,K); init();
        int cnt = 0;
        for(int i = 1; i <= N ; i ++){
            op[++cnt] = Node(1,read(),i);
        }
        int ttt = 0;
        for(int i = 1; i <= N ; i ++){
            Sca(c[i]);
            if(!Hash[c[i]]) Hash[c[i]] = ++ttt;
            c[i] = Hash[c[i]];
        } 
        for(int i = 1; i <= N ; i ++){
            color[i][c[i]] = 1;
            if(K == 1) num[i] = 1;
            else num[i] = 0;
        }
        for(int i = 1; i <= M; i ++){
            int u,v; Sca2(u,v);
            add(u,v); add(v,u);
        }
        int Q; Sca(Q);
        for(int i = 1; i <= Q; i ++){
            op[++cnt] = Node(2,read(),i);
            int k = read();
            for(int j = 0 ; j < k; j ++){
                del[i].pb(read());
            }
        }
        sort(op + 1,op + 1 + cnt,cmp);
        for(int i = 1; i <= cnt; i ++){
            if(op[i].way == 1){
                P.insert(num[op[i].x]); vis[op[i].x] = 1;
                for(int j = head[op[i].x]; ~j; j = edge[j].next){
                    int v = edge[j].to;
                    if(vis[v]){
                        Union(op[i].x,v);
                    }
                }
                
            }else{
                multiset<int>::iterator it;
                for(int j = 0; j < del[op[i].x].size(); j ++){
                    int p = find(del[op[i].x][j]);
                    if(!vis[p]) continue;
                    if(use[p]) continue;
                    use[p] = 1;
                    it = P.find(num[p]);
                    P.erase(it);
                }
                int sum = 0;
                if(P.size()){
                    it = P.end(); it--;
                    sum = *it;
                }
                ans[op[i].x] = sum;
                for(int j = 0 ; j < del[op[i].x].size(); j ++){
                    int p = find(del[op[i].x][j]);
                    if(!vis[p]) continue;
                    if(!use[p]) continue;
                    use[p] = 0;
                    P.insert(num[p]);
                }
            }
        }
        for(int i = 1; i <= Q; i ++) Pri(ans[i]);
        return 0;
    }
  • 相关阅读:
    [整理]正睿 CSP 七连测划水
    关于我想了好久才想出这题咋做这档事
    关于我想了好久才想出这题咋做这档事
    关于我想了好久才想出这题咋做这档事
    [考试总结]ZROI-21-NOIP冲刺-TEST11 总结
    关于我想了很久才想出这题咋做这档事
    [题解]POJ3415 Common Substrings
    [题解]CF1073G Yet Another LCP Problem
    [题解]Codeforces Round #751 (Div. 2) 题解
    [考试总结]ZROI-21-NOIP冲刺-TEST10 总结
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/10958066.html
Copyright © 2020-2023  润新知