1978. 奶牛过马路

题目链接

1978. 奶牛过马路

每天,农夫约翰的 \(N\) 头奶牛都会穿过农场中间的马路。

考虑约翰的农场在二维平面的地图,马路沿水平方向延伸,马路的一侧由直线 \(y=0\) 描述,另一侧由直线 \(y=1\) 描述。

奶牛 \(i\) 从马路一侧的位置 \((a_i,0)\) 沿直线过马路到达另一侧的位置 \((b_i,1)\)

所有 \(a_i\) 互不相同,所有 \(b_i\) 互不相同。

尽管他的奶牛们行动敏捷,他还是担心行动路径交叉的两头奶牛在过马路时发生碰撞。

约翰认为,如果一头奶牛的行动路径没有跟其他任何奶牛的行动路径相交,则该奶牛是安全的。

请帮助约翰计算安全奶牛的数量。

输入格式

第一行包含整数 \(N\)

接下来 \(N\) 行,每行包含两个整数 \(a_i,b_i\),用来描述一头牛的行动路径。

输出格式

输出安全奶牛的数量。

数据范围

\(1≤N≤10^5\),
\(−10^6≤a_i,b_i≤10^6\)

输入样例:

4
-3 4
7 8
10 16
3 9

输出样例:

2

样例解释

第一头牛和第三头牛的行动路线不与其他奶牛的路线相交。

第二头牛和第四头牛的行动路线相交。

解题思路

前缀最值

先将所有点对先按下面那个点排序,对于上面那个点满足要求当且仅当左边点的最大值比它要小且右边点的最小值比它要大,所以现在转换为求某个点左边的最大值和右边的最小值问题,即常用的前缀最值问题

  • 时间复杂度:\(O(nlogn)\)

代码

// Problem: 奶牛过马路
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/description/1980/
// Memory Limit: 64 MB
// Time Limit: 1000 ms

// %%%Skyqwq
#include <bits/stdc++.h>

#define pb push_back
#define fi first
#define se second
#define mp make_pair
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }

template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=1e5+5,inf=0x3f3f3f3f;
int n;
PII a[N];
int Left[N],Right[N];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d%d",&a[i].fi,&a[i].se);
	sort(a+1,a+1+n);
	Left[0]=-inf,Right[n+1]=inf;
	for(int i=1;i<=n;i++)Left[i]=max(a[i].se,Left[i-1]);
	for(int i=n;i>=1;i--)Right[i]=min(a[i].se,Right[i+1]);
	int res=0;
	for(int i=1;i<=n;i++)res+=(a[i].se==Left[i]&&a[i].se==Right[i]);
	printf("%d",res);
	return 0;
}
posted @ 2022-01-29 18:45  zyy2001  阅读(61)  评论(0编辑  收藏  举报