1. 程式人生 > >Gym 101806T Touch The Sky 思維 優先佇列

Gym 101806T Touch The Sky 思維 優先佇列

題目連結:http://codeforces.com/gym/101806/problem/T

 

題意:

        你現在在海拔為0的地方,你現在手上有n個氣球,每個氣球有一個最高可吹海拔L(即如果你當前所在超過了這個高度,你就不能再吹這個氣球),和一個吹完之後升高的高度D,每個氣球只可被用一次,問你最多可以用幾個氣球。

 

做法:

       比賽的時候想到了這個思路,但是沒敢深想。。唉。  按照我們上面所講的,如果我們把一個氣球的L和D相加,得到的All會是什麼?是我們在吹完這個氣球可達到的最高高度,即假設我們使用了這個氣球之後,所在的高度只要低於這個All的值,那麼這個氣球的使用就是合法的。那麼我們就可以維護一個氣球升高之後的一個最低值。所以當然,我們要先將L+D相加做一次排序,每次加入的時候判斷當前高度是否超過了這個氣球的合法值,如果超過,那麼我們肯定要從我們當前所用的氣球裡拿出一個升高距離最大的扔掉(因為當到達這個海拔值的時候,如果我們要保證氣球不減,只能從當前的氣球和已經用掉的氣球裡做一個取捨,那麼很明顯,我們就要把升高高度更高的那個扔掉即可)。

       程式碼量其實很小,唉就是想不到啊。


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=250005;
struct node{
    ll L,D,all;
}e[maxn];
bool cmp(node a,node b){
    return a.all<b.all;
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&e[i].L,&e[i].D);
        e[i].all=e[i].L+e[i].D;
    }
    sort(e+1,e+1+n,cmp);
    ll nowhei=0;
    priority_queue<int> q;
    for(int i=1;i<=n;i++){
        nowhei+=e[i].D;
        q.push(e[i].D);
        if(nowhei>e[i].all){
            int dec=q.top(); q.pop();
            nowhei-=dec;
        }
    }
    printf("%d\n",q.size());
	return 0;
}