CodeCraft-22 and Codeforces Round #795 (Div. 2) E. Number of Groups

一眼并查集

但是怎么维护,借鉴了别人的思路

如果有重叠的话端点一定要重叠,所以用端点来代表线段就可以了

但是暴力连边复杂度受不了

考虑把线段拆成两点,同色的放入一个集合,更新的时候不断合并直至size()==1(==1不erase是因为要留下r最大的,显然只有r最大的有用)

#include<bits/stdc++.h>
using namespace std;
struct lys{
    int col,pos,r,type,id;
};
int fa[2*int(1e5)+5];
int find(int x){
    if(fa[x]!=x) return fa[x]=find(fa[x]);
    else return x;
}
void merge(int x,int y){
    //cout<<"merge :"<<x<<" "<<y<<endl;
    int fx=find(x),fy=find(y);
    fa[fx]=fy;
}
void solve( ){
    int n;
    cin>>n;
    vector<lys>vec;
    for(int i=1;i<=n;i++){
        fa[i]=i;
        int col,x,y;cin>>col>>x>>y;
        vec.push_back((lys){col,x,y,0,i});
        vec.push_back((lys){col,y,-1,1,i});
    }
    sort(vec.begin(), vec.end(), [&](const lys &lhs, const lys& rhs) {
        if(lhs.pos == rhs.pos) return lhs.type < rhs.type;
        return lhs.pos < rhs.pos;
    });
    set<pair<int,int>>s[2];
    for(auto& [col,pos,r,type,id]:vec){
        //cout<<id<<" "<<pos<<" "<<type<<endl;
        if(type==0){ // new segment to add
            s[col].insert({r,id});
            while(s[col^1].size()>1){// 留下r最大的 
               merge(id,s[col^1].begin()->second);
               s[col^1].erase(s[col^1].begin());
            }
            if(!s[col^1].empty()) {
              merge(id,s[col^1].begin()->second);
            }
        }
        else {
            s[col].erase({pos,id});
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++) 
        ans+=(find(i)==i);
    cout<<ans<<endl;
}
int main(){
    //freopen("lys.in","r",stdin);
    int t;cin>>t;
    while(t--){
        solve();
    }
}

 

posted @ 2023-02-05 13:47  liyishui  阅读(20)  评论(0编辑  收藏  举报