[USACO20OPEN]The moo Particle
做题时间:2021.03.02
\(【题目描述】\)
在平面直角坐标系中给定 \(N(N \leq10^5)\)个点\((x_i,y_i)\) ,若对于任意两个点 \((x_i,y_i)\) 和 \((x_j,y_j)\) 满足 \(x_i \leq x_i, y_i \leq y_j\) ,则称它们可以发生反应,反应后其中任意一个点会消失,消失的点不能与其他的点发生反应,求出一个反应顺序,使得反应结束后剩下的点数的最小值。
\(【输入样例】\)
4
1 0
0 1
-1 0
0 -1
\(【输出样例】\)
1
\(【考点】\)
图论
\(【做法】\)
首先想到联系到图论的做法,即从 \(1 \rightarrow n\) 便利每一个点,对于当前点 \(i\) ,查找 \(i+1 \rightarrow n\) 中所有能与它发生反应的点,并连接一条边。最后所有点会变成数个联通快。容易发现,每一个联通块内的所有点都是可以全部反应并消失,最后剩下一个点的,因此最终的答案就是联通块的数量,时间复杂度 \(O(N^2)\)
接着优化以上做法,考虑在枚举 \(1 \rightarrow n\) 时省略 \(O(N)\) 的查找反应点。
对于任意一个点\(i\),如果\(\min\limits_{1\leq j\leq i-1}y_j>\max\limits_{i\leq j\leq n}y_j\),那么表明\([1,i]\)这一段区间内所有的联通快都不能和\([i+1,n]\)这一段区间内的所有联通快连接,因此答案+1。
\(【代码】\)
#include<cstdio>
#include<iomanip>
#include<algorithm>
using namespace std;
const int N=1e5+50;
struct point{
int a,b;
}s[N];
int minel[N],maxnr[N];
int n;
bool cmp(point p,point q)
{
if(p.a!=q.a) return p.a<q.a;
return p.b<q.b;
}
inline int Min(int x,int y){return x<y?x:y;}
inline int Max(int x,int y){return x>y?x:y;}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&s[i].a,&s[i].b);
sort(s+1,s+1+n,cmp);
int cnt=1;
minel[1]=s[1].b,maxnr[n]=s[n].b;
//求最大最小值
for(int i=n-1;i>=1;i--) maxnr[i]=Max(maxnr[i+1],s[i].b);
for(int i=2;i<=n;i++) minel[i]=Min(minel[i-1],s[i].b);
for(int i=1;i<=n;i++){
if(maxnr[i+1]<minel[i]) cnt++;//比较
}
printf("%d\n",cnt);
return 0;
}

浙公网安备 33010602011771号