【JZOJ 3928】【NOIP2014模擬11.6】射擊 (堆)

問題描述
有問題,找副連,無聊的時候當然也可以找他啦。小W找到了他的叔叔——東廠廠長——宇宙超級無敵老WS yy。他們叔侄兩個商量之後決定用彈弓打破社區裏的一些窗戶,但是彈弓每秒只能徹底打破一扇窗戶。而且如果某戶窗戶的主人回來了的話,他們就不能進行破壞了(不然會死得很慘的)。因爲有的人裝的玻璃好,有的人裝的玻璃差,有的人裝的玻璃高,有的人裝的玻璃矮,所以你不能要求他們叔侄兩個打破不同的窗戶獲得的快樂值必須相同。現在他們想知道在能活着的情況下能夠獲得的最大快樂值。
輸入
第一行一個正整數n,表示共有n個窗戶。
接下來n行,每行兩個整數,第一個爲窗子的主人回來的時刻(秒),第二個爲破壞該窗戶所能獲得的快樂值。
輸出
最大的快樂值。
樣例輸入
4
1 19
2 10
1 20
2 15
樣例輸出
35
樣例說明:
在第0個時刻,他們選擇破壞掉3號窗戶,在第1個時刻,因爲1號窗戶的主人已經回來了,所以不能去破壞1號窗戶,只能去破壞2號窗戶或4號窗戶,顯然選擇4號窗戶。總的快樂值就是20+15=35。
數據範圍
20%的數據,n<=100。
40%的數據,n<=50000。
100%的數據,n<=200000,快樂值的絕對值不超過32767,時刻非負且小於2^31。
算法討論
我 們 把窗 戶 按照 時間 排序,之後反 過來 做。
對 於每一 個時間 段,我 們 不妨假 設它 的 長爲 cur 。那 麼顯 然,在 這個時間 段後面的所有窗 戶 都是 可以打的。所以我 們 可以用一 個 堆 來維護當 前 時間 段後面的窗 戶 : 對 於每 個時間 段 cur ,我 們 取 最大的 cur 個 窗 戶來 打破。

#include <cstdio>
#include <queue>
#include <algorithm>
#define MAX_N 200006
using namespace std;
struct arr
{
    int t,w;
}a[MAX_N];
int n;
long long s;
priority_queue <int> q;

bool cmp(arr x,arr y)
{
    return x.t>y.t;
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i].t,&a[i].w);
        if (a[i].t>n)
            a[i].t=n;
    }
    sort(a+1,a+n+1,cmp);
    int j=1;
    for (int i=a[1].t;i>=1;i--)
    {
        while (a[j].t==i)
        {
            if (a[j].w>0)
                q.push(a[j].w);
            j++;
        }
        if (!q.empty())
        {
            s+=q.top();
            q.pop();
        }
    }
    printf("%lld",s);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章