題目連結:http://www.lydsy.com/JudgeOnline/problem.php?id=3314
題意:
N頭牛在一個座標軸上,每頭牛有個高度。現給出一個距離值D。
如果某頭牛在它的左邊,在距離D的範圍內,如果找到某個牛的高度至少是它的兩倍,且在右邊也能找到這樣的牛的話。則此牛會感覺到不舒服。
問有多少頭會感到不舒服。
題解:
從左到右、從右到左兩遍單調佇列。
單調性:
(1)座標x遞增。
(2)高度h遞減。
維護單調性:
(1)從隊首開始,所有與當前牛i的距離超過d的,以後都不會再用到。
(2)從隊尾開始,所有高度 <= 當前高度h[i]的,都不會再用到,因為當前牛i一定比前面的更優(又高又近)。
(3)最後再將i壓入隊尾。
每次判斷一下之前最高的牛(隊首)是不是h[i]的兩倍,如果是則cnt[i]++。
最後統計一下cnt[i] == 2的個數就好。
AC Code:
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #define MAX_N 50005 using namespace std; struct Data { int x; int h; Data(int _x,int _h) { x=_x; h=_h; } Data(){} friend bool operator < (const Data &a,const Data &b) { return a.x<b.x; } }; int n,d; int head; int tail; int ans=0; int q[MAX_N]; int cnt[MAX_N]; Data dat[MAX_N]; void read() { cin>>n>>d; for(int i=0;i<n;i++) { cin>>dat[i].x>>dat[i].h; } } void solve() { sort(dat,dat+n); memset(cnt,0,sizeof(cnt)); head=0; tail=0; for(int i=0;i<n;i++) { while(head<tail && dat[i].x-dat[q[head]].x>d) head++; while(head<tail && dat[q[tail-1]].h<=dat[i].h) tail--; if(head<tail && dat[q[head]].h>=dat[i].h*2) cnt[i]++; q[tail++]=i; } head=0; tail=0; for(int i=n-1;i>=0;i--) { while(head<tail && dat[q[head]].x-dat[i].x>d) head++; while(head<tail && dat[q[tail-1]].h<=dat[i].h) tail--; if(head<tail && dat[q[head]].h>=dat[i].h*2) cnt[i]++; q[tail++]=i; } for(int i=0;i<n;i++) { if(cnt[i]==2) ans++; } } void print() { cout<<ans<<endl; } int main() { read(); solve(); print(); }