zoukankan      html  css  js  c++  java
  • A All-Star Game(维护连通分量大小,线段树+可撤回并查集)

    题:https://ac.nowcoder.com/acm/contest/5673/A

    题意:有n个球员m个粉丝,每个粉丝可以是若干个球员的粉丝,现要准备一场比赛,问最少安排多少个球员让所有粉丝都想看比赛(想看比赛得是有粉丝喜爱的球迷登场),还要提供询问操作:粉丝成为球员的粉丝,粉丝撤销成为球员的粉丝

    分析:将粉丝开始成为球员粉丝到撤销成为球员粉丝定成一个时间区间,总共有q个询问时间大小就为q,这个q刚好可以表示上线段树上的n,那么处理输出就是在叶子节点进行操作,对于时间区间的处理用并查集维护其连通性,其中用栈记录曾经的相关值,在跳出这个时间区间的时候直接按出栈顺序返回恢复以前的值即可

    #include<bits/stdc++.h>
    using namespace std;
    #define lson root<<1,l,midd
    #define rson root<<1|1,midd+1,r
    #define pb push_back
    #define ull unsigned long long
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long ll;
    const ll INF=1e18;
    const int M=5e5+6;
    int Rank[M],fa[M],lst[M*10],red[M*10];
    struct node{
        int u,v;
    }e[M*10];
    map<pii,int>mp;
    vector<int>tr[M<<2];
    int ans,sum,top,n,m,q,tot;
    void update(int L,int R,int id,int root,int l,int r){
        if(L<=l&&r<=R){
            tr[root].pb(id);
            ///cout<<id<<"!!"<<endl;
            return;
        }
        int midd=(l+r)>>1;
        if(L<=midd)update(L,R,id,lson);
        if(R>midd)update(L,R,id,rson);
    }
    struct Node{
        int fau,fav,rku,rkv,sum,ans;
    }sta[M*10];
    int Find(int x){
        return x==fa[x]?x:Find(fa[x]);
    }
    void Union(int x,int y){
        top++;
        x=Find(x),y=Find(y);
        sta[top].fau=x,sta[top].fav=y;
        sta[top].rku=Rank[x],sta[top].rkv=Rank[y];
        sta[top].sum=sum,sta[top].ans=ans;
        if(x==y)return;
        if(x<=n&&y>n){///粉丝y没有偶像
            sum++;
            if(Rank[x]==1)///偶像x没有粉丝
                ans++;
        }
        else{
            if(Rank[x]!=1&&Rank[y]!=1)///粉丝z有偶像y,现在z喜欢的偶像x也原本有粉丝
                ans--;
        }
        if(Rank[x]<Rank[y])swap(x,y);
        if(Rank[x]==Rank[y])Rank[x]++;
        fa[y]=x;
    }
    ///由于栈记录了之前步骤,所以依次撤销操作即可
    void stapop(){
        fa[sta[top].fau]=sta[top].fau;
        fa[sta[top].fav]=sta[top].fav;
        Rank[sta[top].fau]=sta[top].rku;
        Rank[sta[top].fav]=sta[top].rkv;
        sum=sta[top].sum,ans=sta[top].ans;
        top--;
    }
    void query(int root,int l,int r){
        for(auto i:tr[root])
            Union(e[i].u,e[i].v);
        if(l==r){
            if(sum!=m)///没有所有粉丝都能看到
                puts("-1");
            else printf("%d
    ",ans);
        }
        else{
            int midd=(l+r)>>1;
            query(lson);
            query(rson);
        }
        int len=tr[root].size();
        while(len--){
            stapop();
        }
    }
    int main(){
        scanf("%d%d%d",&n,&m,&q);
        ///球员1~n,粉丝n+1~n+m
        for(int i=1;i<=n+m;i++){
            Rank[i]=1;
            fa[i]=i;
        }
        for(int i=1;i<=n;i++){
            int k;
            scanf("%d",&k);
            while(k--){
                int v;
                scanf("%d",&v),v+=n;
                if(!mp.count(MP(i,v))){
                    mp[MP(i,v)]=++tot;
                    e[tot]=node{i,v};
                }
                lst[tot]=1;
            }
        }
        for(int i=1;i<=q;i++){
            int u,v;
            scanf("%d%d",&v,&u);
            v+=n;
            if(!mp.count(MP(u,v))){
                mp[MP(u,v)]=++tot;
                e[tot]=node{u,v};
            }
            int id=mp[MP(u,v)];
            if(lst[id]==0)
                lst[id]=i;
            else{
                red[id]=i-1;
                if(i!=1)
                    update(lst[id],red[id],id,1,1,q);
                lst[id]=red[id]=0;
            }
        }
        ///把到最后也没有消除的边人为地加上在q时刻结束
        for(int i=1;i<=tot;i++)
            if(lst[i]){
                red[i]=q;
                update(lst[i],red[i],i,1,1,q);
            }
        query(1,1,q);
        return 0;
    }
    View Code
  • 相关阅读:
    前端几个常用简单的开发手册拿走不谢
    初中级前端开发工程师如何提升个人能力?
    初中级前端开发工程师如何提升个人能力?
    【程序人生】那些工作之外的技术挣钱方式
    Java EE (13) -- 常用的基础结构模式
    3、数据类型
    洛谷——P2299 Mzc和体委的争夺战
    codevs——T1214 线段覆盖
    洛谷——P1106 删数问题
    洛谷——P1031 均分纸牌
  • 原文地址:https://www.cnblogs.com/starve/p/13538234.html
Copyright © 2011-2022 走看看