BZOJ : [Usaco2013 Nov]Crowded 单调队列
正反两遍个来一次单调队列 DP 即可.
Code:
#include<cstdio> #include<deque> #include<algorithm> using namespace std; const int maxn = 50000+3; int mark[maxn]; struct Node{ long long pos,height; Node(long long pos=0,long long height=0):pos(pos),height(height){} bool operator<(Node b)const{ if(b.pos == pos)return height > b.height; return pos<b.pos; } }A[maxn]; deque<Node>Q; int main(){ // freopen("in.txt","r",stdin); int n; long long d; scanf("%d%lld",&n,&d); for(int i =1;i<=n;++i) { long long a,b; scanf("%lld%lld",&a,&b); A[i]=Node(a,b); } sort(A+1,A+1+n); int cnt = 0; for(int i = 1;i <= n; ++i) { long long cur_pos = A[i].pos-d; long long cur_height = A[i].height; while(!Q.empty()&&Q.front().pos < cur_pos)Q.pop_front(); while(!Q.empty()&&Q.back().height <= cur_height)Q.pop_back(); Q.push_back(A[i]); if(Q.front().height >= A[i].height*2)mark[i] = 1; } while(!Q.empty())Q.pop_back(); for(int i =n;i>=1;--i){ long long cur_pos = A[i].pos + d; long long cur_height = A[i].height; while(!Q.empty()&&Q.front().pos > cur_pos)Q.pop_front(); while(!Q.empty()&&Q.back().height <= cur_height)Q.pop_back(); Q.push_back(A[i]); if(Q.front().height >= A[i].height*2&&mark[i])++cnt; } printf("%d",cnt); return 0; }