[USACO13NOV]挤奶牛Crowded Cows(洛谷 P3088)

题目描述

Farmer John’s N cows (1 <= N <= 50,000) are grazing along a one-dimensional fence. Cow i is standing at location x(i) and has height h(i) (1 <= x(i),h(i) <= 1,000,000,000).

A cow feels “crowded” if there is another cow at least twice her height within distance D on her left, and also another cow at least twice her height within distance D on her right (1 <= D <= 1,000,000,000). Since crowded cows produce less milk, Farmer John would like to count the number of such cows. Please help him.

FJ有N(1 <= N <= 50,000)头奶牛沿着一维的栅栏吃草,第i头奶牛在目标点x(i) ,它的身高是 h(i) (1 <=x(i),h(i) <= 1,000,000,000)。

当一头奶牛左边D距离内而且右边D距离内有身高至少是它的两倍的奶牛,t (1 <= D <= 1,000,000,000),它就会觉得拥挤。

请计算觉得拥挤的奶牛的数量。

输入格式

  • Line 1: Two integers, N and D.

  • Lines 2…1+N: Line i+1 contains the integers x(i) and h(i). The locations of all N cows are distinct.

输出格式

  • Line 1: The number of crowded cows.

输入 #1

6 4
10 3
6 2
5 3
9 7
3 6
11 2

输出 #1

2

跑两遍单调队列,每一遍都维护一个单调递减的队列,对符合的元素进行标记;当一个元素被标记两遍以后,符合要求;两遍单调队列难想,其他的都是单调队列板子;

代码:

#include
using namespace std;
struct Node{
	int x,h;
}a[50100];
bool cmp(Node p,Node q){
	return p.x<q.x;
}
struct Nod{
	int post,date;
}sta[50100];
bool vis[50100][3];
int main(){
	int n,d;
	scanf("%d%d",&n,&d);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&a[i].x,&a[i].h);
	}
	sort(a+1,a+n+1,cmp);
	int ans=1,head=1;
	for(int i=1;i<=n;i++){
		while(head<=ans&&sta[ans].date<=a[i].h){
			ans--;
		}
		sta[++ans].date=a[i].h;
		sta[ans].post=a[i].x;
		if(ans==1) continue;
		while(head<=ans&&sta[head].post<a[i].x-d){
			head++;
		}
		if(sta[head].date>=2*a[i].h){
			//cout<
			vis[i][1]=true;
		}
	}
	for(int i=1;i<=n;i++){
		sta[i].date=sta[i].post=0;//清0,特别注意
	}
	ans=1,head=1;
	for(int i=n;i>=1;i--){
		while(head<=ans&&sta[ans].date<=a[i].h){
			ans--;
		}
		sta[++ans].date=a[i].h;
		sta[ans].post=a[i].x;
		if(ans==1) continue;
		while(head<=ans&&sta[head].post>a[i].x+d){
			head++;
		}
		if(sta[head].date>=2*a[i].h){
			//cout<
			vis[i][2]=true;
		}
	}
	int sum=0;
	for(int i=1;i<=n;i++){
		if(vis[i][1]&&vis[i][2]){
			sum++;
		}
	}
	printf("%d\n",sum);
	return 0;
}

你可能感兴趣的:(#,单调队列)