【题解】P3088

传送门

思路

当一头奶牛左边D距离内而且右边D距离内有身高至少是它的两倍的奶牛

不难想到使用单调队列(机房大佬Canstant0x5F3759DF使用的线段树我是不会)

从左到右、从右到左各扫一遍即可。

代码

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#define int long long
using namespace std;

const int MAXN = 5e4 + 5;

int n, d, cnt;
bool ans1[MAXN], ans2[MAXN];
deque<int> q;

struct cow
{
	int x, h;
	bool operator <(const cow &p)const
	{
		return x < p.x;
	}
}a[MAXN];

signed main()
{
	scanf("%lld%lld", &n, &d);
	for (int i = 1; i <= n; i++)
	{
		scanf("%lld%lld", &a[i].x, &a[i].h);
	}
	sort(a + 1, a + n + 1);
	for (int i = 1; i <= n; i++)
	{
		while (!q.empty() && a[q.back()].h < a[i].h)
		{
			q.pop_back();
		}
		while (!q.empty() && a[i].x - a[q.front()].x > d)
		{
			q.pop_front();
		}
		q.push_back(i);
		if (a[q.front()].h >= (a[i].h << 1)) //等价于a[i].h * 2
		{
			ans1[i] = true;
		}
	}
	q.clear();
	for (int i = n; i; i--)
	{
		while (!q.empty() && a[q.back()].h < a[i].h)
		{
			q.pop_back();
		}
		while (!q.empty() && a[q.front()].x - a[i].x > d)
		{
			q.pop_front();
		}
		q.push_back(i);
		if (a[q.front()].h >= (a[i].h << 1))
		{
			ans2[i] = true;
		}
	}
	for (int i = 1; i <= n; i++)
	{
		if (ans1[i] && ans2[i]) //如果两个同时满足
		{
			cnt++;
		}
	}
	printf("%lld", cnt);
	return 0;
}
上一篇:queue


下一篇:算法与数据结构基础<三>----数据结构基础之栈和队列加强之实现双端队列