USACO 2013 November Contest, Silver Problem 2. Crowded Cows 单调队列

Problem 2: Crowded Cows [Brian Dean, 2013]

Farmer John's N cows (1 <= N <= 50,000) are grazing along a one-dimensional fence. Cow i is standing at location x(i) and has height h(i) (1 <= x(i),h(i) <= 1,000,000,000).

A cow feels "crowded" if there is another cow at least twice her height within distance D on her left, and also another cow at least twice her height within distance D on her right (1 <= D <= 1,000,000,000). Since crowded cows produce less milk, Farmer John would like to count the number of such cows. Please help him.

PROBLEM NAME: crowded

INPUT FORMAT:

* Line 1: Two integers, N and D.

* Lines 2..1+N: Line i+1 contains the integers x(i) and h(i). The locations of all N cows are distinct.

SAMPLE INPUT (file crowded.in):

6 4
10 3
6 2
5 3
9 7
3 6
11 2

INPUT DETAILS:

There are 6 cows, with a distance threshold of 4 for feeling crowded. Cow #1 lives at position x=10 and has height h=3, and so on.

OUTPUT FORMAT:

* Line 1: The number of crowded cows.

SAMPLE OUTPUT (file crowded.out):

2 

OUTPUT DETAILS: The cows at positions x=5 and x=6 are both crowded.

分析

首先不难想到先按照奶牛的位置进行排序。

这道题的关键在于维护一个单调队列。当一个新的奶牛需要入队时,先和队尾进行比较。如果队尾奶牛高度小于需要入队的奶牛高度,那么删除队尾。直到满足队尾奶牛高度大于需要入队的奶牛高度。(因为如果后面的奶牛感到拥挤,有了这个入队的奶牛,这些被删除的奶牛已经不再有必要性了)

插入这个奶牛时,再与队头的奶牛比较删除队头奶牛,直到插入奶牛与队头奶牛之间的距离小于等于D。(因为距离大于D的奶牛已经不会再对之后的奶牛造成影响了)

最后比较插入奶牛的身高与队头奶牛身高(此时队头奶牛身高最高且距离小于等于D)。如果满足大于两倍身高那么说明在这个奶牛的左面已经感到拥挤了。

然后把上述过程反过来从右向左维护单调队列。

最后从1~n的奶牛中寻找,如果奶牛在左右两侧都有满足要求会使它感到拥挤的奶牛,那么这是一个合法情况,将计数器加1。

我自己写程序犯了一些小错误:把某两个cows写成了Q。所以同类型的变量写的时候还是过一下脑子自己在写什么蛤。

程序

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MAX = 50000 + 1;
 4 int n, d;
 5 struct cow
 6 {
 7     int x,h;
 8 }cows[MAX];
 9 inline bool cmp(cow a, cow b)
10 {
11     return a.x < b.x;
12 }
13 int main()
14 {
15     cin >> n >> d;
16     for (int i = 1; i <= n; i++)
17         cin >> cows[i].x >> cows[i].h;
18     sort(cows+1, cows+(n+1), cmp);
19     cow Q[MAX];
20     int Head = 1, Tail = 0;
21     bool vis[MAX], vis2[MAX];
22     for(int i = 1; i <= n; i++)
23     {
24         while(Head <= Tail && Q[Tail].h < cows[i].h)
25             Tail--;
26         Q[++Tail] = cows[i];
27         while(Head <= Tail && Q[Head].x < cows[i].x-d)
28             Head++;
29         if(Q[Head].h >= cows[i].h*2)
30             vis[i]=true;
31     }
32     memset(Q, 0, sizeof(Q));
33     Head=1;
34     Tail=0;
35     for(int i = n; i >= 1; i--)
36     {
37         while(Head <= Tail && Q[Tail].h < cows[i].h)
38             Tail--;
39         Q[++Tail] = cows[i];
40         while(Head <= Tail && Q[Head].x > cows[i].x+d)
41             Head++;
42         if(Q[Head].h >= cows[i].h*2)
43             vis2[i]=true;
44     }
45     int ans=0;
46     for(int i = 1; i <= n; i++)
47     {
48         if(vis[i] && vis2[i])
49             ans++;
50         //cout << vis[i] << vis2[i] << endl;
51     }
52     printf("%d",ans);
53     return 0;
54 }

 

posted @ 2018-01-21 11:02  OptimusPrime_L  阅读(302)  评论(0编辑  收藏  举报