多刷水题有益身心健康……
维护一个堆(单调队列和线段树也可以吧),记录在当前节点前且在距离范围内的以高度为关键字的大根堆。
若当前堆顶的位置超出范围,就把这个节点pop掉。
若当前堆顶的高度满足条件,就把计数的数组加1。
最后统计有多少节点的计数数组的值为2,个数就是答案。
附上AC代码:
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <queue>
using namespace std;
struct note{
int wz,h;
bool operator < (const note lyf) const {return h<lyf.h;}
}a[50010],t;
priority_queue <note> que;
int n,m,c[50010],ans;
inline char nc(){
static char ch[100010],*p1=ch,*p2=ch;
return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &a){
static char c=nc();int f=1;
for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
for (a=0;isdigit(c);a=a*10+c-'0',c=nc());
a*=f;return;
}
inline bool cmp(note p,note q){
return p.wz<q.wz;
}
int main(void){
read(n),read(m);
for (int i=1; i<=n; ++i) read(a[i].wz),read(a[i].h);
sort(a+1,a+1+n,cmp);
for (int i=1; i<=n; ++i){
while (!que.empty()&&que.top().wz+m<a[i].wz) que.pop();
if (!que.empty()&&que.top().h>=(a[i].h<<1)) ++c[i];
que.push(a[i]);
}
while (!que.empty()) que.pop();
for (int i=n; i>=1; --i){
while (!que.empty()&&que.top().wz-m>a[i].wz) que.pop();
if (!que.empty()&&que.top().h>=(a[i].h<<1)) ++c[i];
que.push(a[i]);
}
for (int i=1; i<=n; ++i) if (c[i]==2) ++ans;
printf("%d",ans);
return 0;
}
做题心得:第一次帮老师改题,心中有点小激动……看来我还是有点用处滴……