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(); } }