题目描述
FJ的n头奶牛(1<=n<=50000)在被放养在一维的牧场。第i头奶牛站在位置x(i),并且x(i)处有一个高度值h(i)(1<=x(i),h(i)<=1000000000)。
一头奶牛感觉到拥挤当且仅当它的左右两端都有一头奶牛所在的高度至少是它的2倍,且和它的距离最多为D。尽管感到拥挤的奶牛会产生更少的牛奶,FJ还是想知道一共有多上感到拥挤的奶牛。请你帮助他。
输入
第一行:两个整数n和D。
第二行到第n+1行:每一行有两个数表示x(i)和h(i)。
输出
一个数k表示感到拥挤的奶牛的数量。
样例输入
Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
6 4
10 3
6 2
5 3
9 7
3 6
11 2
样例输出
2
思路
这道题是典型的单调队列的题。要把每头奶牛遍历一遍,查找它前后D距离以内的不矮于自身高度2倍的牛。这里做一个推导:如果一个范围以内最高的牛都不够高,那它肯定不会觉得拥挤。
所以,分别找每个奶牛前后D距离内最高的奶牛是否不矮于自身高度2倍,再把觉得拥挤的牛统计起来就可以了。
用一个递减单调队列存每个奶牛,每次入牛时把它前面矮于它的奶牛都踢出,还要把队首所有坐标不在距离D范围以内的奶牛出队,最后判断队首的奶牛是否足够高就完了。
这样遍历前、后各一次,两次都觉得拥挤的奶牛才把它加上。
代码如下,以理解的就不用看了。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long int
using namespace std;
LL n,m,i,j,f[50005],l,r,k;
bool v[50005];
struct itn{
LL x,h;
itn(){}
itn(LL X,LL H){
x=X,h=H;
}
}cow[50005];
inline LL read(){ //读入优化
LL x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
inline bool cmp(itn a,itn b){
return a.x<b.x;
}
int main()
{
n=read(),m=read();
for(i=1;i<=n;i++)cow[i].x=read(),cow[i].h=read();
sort(cow+1,cow+1+n,cmp);
for(i=1;i<=n;i++){
while(r>l&&cow[f[l]].x<cow[i].x-m)l++;
if(r>l&&cow[f[l]].h>=cow[i].h*2)v[i]=1;
while(r>l&&cow[f[r-1]].h<cow[i].h)r--;
f[r++]=i;
}
l=r=0;
for(i=n;i>0;i--){
while(r>l&&cow[f[l]].x>cow[i].x+m)l++;
if(r>l&&cow[f[l]].h>=cow[i].h*2&&v[i])k++;
while(r>l&&cow[f[r-1]].h<cow[i].h)r--;
f[r++]=i;
}
printf("%lld",k);
putchar('\n');
return 0;
}
欢迎关注我的博客 偶耶(xiong j x)