CF--795--E
关键
感觉是一个很神奇的合并的方法。
首先对这个区间进行左右拆点,然后进行排序处理。
如果加进来的这个点是左端点,那就把在区间里面的左端点进行合并。
如果加进来的是右端点,那就把相对应的左端点进行删除就可以了。
就是没有那些特别复杂的判断了。
这题是检查连通块的数量,所以只需要取最右边的那个点就行了,set里面存储的东西变一下子就可以了。
代码
#include <bits/stdc++.h> using namespace std; using pii=pair<int,int>; const int M=1e5+5; #define fi fist #define se second inline int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } struct node { int c,l,r; }a[M]; int fa[M]; int find(int x) { return x==fa[x]?fa[x]:fa[x]=find(fa[x]); } void merge(int x,int y) { fa[find(x)]=find(y); } int main() { int TT=read(); while(TT--) { int n=read(); vector<pii>v; for(int i=1;i<=n;i++) { fa[i]=i; a[i].c=read(),a[i].l=read(),a[i].r=read(); v.push_back({a[i].l,-i});//左边的优先级更高,所以是负的 v.push_back({a[i].r,i}); } sort(v.begin(),v.end()); set<pii>se[2]; for(int i=0;i<v.size();i++) { auto [x,id]=v[i];//这个值 if(id<0) { id=-id;//进来 se[a[id].c].insert({a[id].r,id}); int tmp=a[id].c^1;//去另一边合并 while(se[tmp].size()>1) { int y=se[tmp].begin()->second; se[tmp].erase(se[tmp].begin()); merge(id,y); } if(se[tmp].size()==1)merge(se[tmp].begin()->second,id);//这最后一个也要进行合并,其他的全部进行删除 } else se[a[id].c].erase({a[id].r,id}); } int ans=0; for(int i=1;i<=n;i++) if(fa[i]==i)ans++; cout<<ans<<endl; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通