1. 程式人生 > >P3088 [USACO13NOV]擠奶牛Crowded Cows(單調隊列)

P3088 [USACO13NOV]擠奶牛Crowded Cows(單調隊列)

nlogn most cow 大於 -o adg style pap total


題目描述

Farmer John has N cows that need to be milked (1 <= N <= 10,000), each of which takes only one unit of time to milk.

Being impatient animals, some cows will refuse to be milked if Farmer John waits too long to milk them. More specifically, cow i produces g_i gallons of milk (1 <= g_i <= 1000), but only if she is milked before a deadline at time d_i (1 <= d_i <= 10,000). Time starts at t=0, so at most x total cows can be milked prior to a deadline at time t=x.

Please help Farmer John determine the maximum amount of milk that he can obtain if he milks the cows optimally.

FJ有N(1 <= N <= 10,000)頭牛要擠牛奶,每頭牛需要花費1單位時間。

奶牛很厭煩等待,奶牛i在它的截止時間d_i (1 <= d_i <= 10,000)前擠g(1 <= g_i <= 1000)的奶,否則將不能擠奶。時間t開始時為0,即在時間t=x時,最多可以擠x頭奶牛。

請計算FJ的最大擠奶量。

輸入輸出格式

輸入格式:

* Line 1: The value of N.

* Lines 2..1+N: Line i+1 contains the integers g_i and d_i.

輸出格式:

* Line 1: The maximum number of gallons of milk Farmer John can obtain.

輸入輸出樣例

輸入樣例#1: 復制
4 
10 3 
7 5 
8 1 
2 1 
輸出樣例#1: 復制
25 

說明

There are 4 cows. The first produces 10 gallons of milk if milked by time 3, and so on.

Farmer John milks cow 3 first, giving up on cow 4 since she cannot be milked by her deadline due to the conflict with cow 3. Farmer John then milks cows 1 and 2.



樓下STL的nlogn做法也很巧妙啊

這裏說一下O(n)的單調隊列做法

首先每個元素肯定要按照位置排序,然後依次進隊,判斷如果隊尾的數大小小於要進隊的數,那就把隊尾彈出,直到隊尾的數大於等於要進隊的數

這是為了維護單調性

然後再判斷如果隊頭的數位置的差值大於d,出隊,直到差值小於d,此時隊頭的數為單調隊列內的合法最大值

因此只要將要進隊的數與目前的隊頭元素比較即可

這樣維護了前面的,後面的反一下就好了

時間復雜度:因為每個元素最多進隊出隊一次,所以是O(n)的

單調隊列有單向性,這個題對兩邊都有要求,所以要正反向跑兩次。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct ppap{
 4     int x,y;
 5 }a[100001];
 6 ppap qq[100001];
 7 bool q[100001],h[100001];
 8 inline bool cmp(ppap a,ppap b){return a.x<b.x;}
 9 int main()
10 {
11     int n,d;scanf("%d%d",&n,&d);
12     for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
13     sort(a+1,a+n+1,cmp);
14     int l=1,r=0;
15     for(int i=1;i<=n;i++){
16         while(l<=r&&qq[r].y<a[i].y)r--;
17         qq[++r]=a[i];
18         while(l<=r&&qq[l].x<a[i].x-d)l++;
19         if(qq[l].y>=a[i].y*2)q[i]=1;
20     }
21     memset(qq,0,sizeof qq);l=1;r=0;
22     for(int i=n;i;i--){
23         while(l<=r&&qq[r].y<a[i].y)r--;
24         qq[++r]=a[i];
25         while(l<=r&&qq[l].x>a[i].x+d)l++;
26         if(qq[l].y>=a[i].y*2)h[i]=1;
27     }
28     int ans=0;
29     for(int i=1;i<=n;i++)if(q[i]&&h[i])ans++;
30     printf("%d",ans);
31     return 0;
32 }

P3088 [USACO13NOV]擠奶牛Crowded Cows(單調隊列)