1. 程式人生 > >【貪心】家庭作業(連結串列優化)

【貪心】家庭作業(連結串列優化)

問題 I: 【貪心】家庭作業

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 4  解決: 2
[提交] [狀態] [討論版] [命題人:admin]

題目描述

老師在開學第一天就把所有作業都佈置了,每個作業如果在規定的時間內交上來的話才有學分。每個作業的截止日期和學分可能是不同的。例如如果一個作業學分為10,要求在6天內交,那麼要想拿到這10學分,就必須在第6天結束前交。
每個作業的完成時間都是隻有一天。例如,假設有7次作業的學分和完成時間如下:

老師在開學第一天就把所有作業都佈置了,每個作業如果在規定的時間內交上來的話才有學分。每個作業的截止日期和學分可能是不同的。例如如果一個作業學分為10,要求在6天內交,那麼要想拿到這10學分,就必須在第6天結束前交。
每個作業的完成時間都是隻有一天。例如,假設有7次作業的學分和完成時間如下:

輸入

第一行一個整數N,表示作業的數量;
接下來N行,每行包括兩個整數,第一個整數表示作業的完成期限,第二個數表示該作業的學分。

輸出

輸出一個整數表示可以獲得的最大學分。保證答案不超過C/C++的int範圍。

樣例輸入

7
1 6
1 7
3 2
3 1
2 4
2 5
6 1

樣例輸出

15

提示

對於20%的資料,N≤103;
對於40%的資料,N≤104;
對於60%的資料,N≤105;
對於100%的資料,N≤106,作業的完成期限均小於7×105

[提交][狀態]

【分析】

將作業按分數降序,同分按時限降序。

對每一天構造一個指標,初始時,i指向i-1,當安排第一個作業時,儘量靠後安排,因此在該作業時限之前找一個空閒的天安排上。同時更新指標,使得所有天的指標總是指向前面最靠近的空閒的天。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
 
struct PII{
    int score,day;
}p[1010101];
bool cmp(PII a,PII b)
{
    if(a.score==b.score)return a.day>b.day;
    return a.score>b.score;
}
int n;
int pre[1010101];
bool vis[1010100];
int father(int day)
{
    if(!vis[day])
        return day;
    return pre[day]=father(pre[day]);
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)scanf("%d%d",&p[i].day,&p[i].score);
    sort(p,p+n,cmp);
    for(int i=1;i<=700000;i++)pre[i]=i-1,vis[i]=false;
    int ans=0;
    for(int i=0;i<n;i++)
    {
        int ok=father(p[i].day);
        if(ok==0)continue;
        vis[ok]=true;
        ans+=p[i].score;
    }
    printf("%d\n",ans);
}