[MCO 2025] Rectangle Connections 题解
[MCO 2025] Rectangle Connections
解法说明
分析题意
根据题意发现,如果两个区域的 \([x_{i,1},x_{i,2}],[x_{j,1},x_{j,2}]\) 或 \([y_{i,1},y_{i,2}],[y_{j,1},y_{j,2}]\) 存在交集,那么这两个区域就可以互相连通。
此时,题意转化为:给定图中有多少个连通块。
算法步骤
我们考虑对 \(x,y\) 两个方向分别进行处理。
首先每个区间 \([x_{i,l},x_{i,r}]\),按区间起点排序。
然后进行线性扫描,维护当前合并段的终点与该段的编号。
若当前区间起点小于当前合并段的终点 ,说明与当前段有重叠,更新当前合并段的终点,并使用并查集进行合并。
否则开启新的合并段。
\(y\) 方向同理。
参考代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int m;
struct Node{
pair<int,int> loc;
int id;
friend bool operator < (const Node& a,const Node& b){
return a.loc<b.loc;
}
};
/* 并查集 */
int r[N];
int finds(int x){
if(r[x]==x)return x;
r[x]=finds(r[x]);
return r[x];
}
/*---------*/
int main(){
//freopen("read.in","r",stdin);
vector<Node> x,y;//两个方向分别的线段
scanf("%d",&m);
for(int i=1;i<=m;++i){
int lx1,lx2,ly1,ly2;
scanf("%d%d%d%d",&lx1,&lx2,&ly1,&ly2);
x.push_back({{lx1,lx2},i});
y.push_back({{ly1,ly2},i});
r[i]=i;
}
int num=m;//统计连通块的数量
sort(x.begin(),x.end());
sort(y.begin(),y.end());
int lst=-1;
int lstid=-1;
for(auto i:x){
if(i.loc.first<=lst){
//包含则合并
lst=max(lst,i.loc.second);
int f1=finds(lstid);
int f2=finds(i.id);
if(f1!=f2){
r[f1]=f2;
num--;//统计连通块
}
}else{
//否则更新新的连通块终点和连通块编号
lst=i.loc.second;
lstid=i.id;
}
}
lst=-1;
lstid=-1;
//由于一个区域可以拐弯(x,y可以相互转换),所以说x,y使用同一个并查集
for(auto i:y){
if(i.loc.first<=lst){
lst=max(lst,i.loc.second);
int f1=finds(lstid);
int f2=finds(i.id);
if(f1!=f2){
r[f1]=f2;
num--;
}
}else{
lst=i.loc.second;
lstid=i.id;
}
}
printf("%d",num);
}

浙公网安备 33010602011771号