有N个任务,每个任务有一个最晚结束时间以及一个对应的奖励。在结束时间之前完成该任务,就可以获得对应的奖励。完成每一个任务所需的时间都是1个单位时间。有时候完成所有任务是不可能的,因为时间上可能会有冲突,这需要你来取舍。求能够获得的最高奖励。
输入
第1行:一个数N,表示任务的数量(2 <= N <= 50000)
第2 - N + 1行,每行2个数,中间用空格分隔,表示任务的最晚结束时间E[i]以及对应的奖励W[i]。(1 <= E[i] <= 10^9,1 <= W[i] <= 10^9)
输出
输出能够获得的最高奖励。
输入样例
7
4 20
2 60
4 70
3 40
1 30
4 50
6 10
输出样例
230
解法:
按任务结束时间排序, O(n)向后扫描, 维护一个长度为当前可选的总任务量的最优解
则有, 若新任务比当前总任务还靠后, 则直接添加, 对任务不影响。
当前任务结束时间和当前总任务量相同时, 则必有可以替换掉当前最优解中的最小值达到更优。(因为此任务替换于当前最优解中的任何任务都满足题意)
因此最终求得最优解
可以用优先队列维护 总复杂的O(nlongn)
typedef long long ll;
const int MAXN = 1e6 + 10;
struct node
{
int endtime, val;
}arr[MAXN];
bool cmp(node a, node b)
{
return a.endtime < b.endtime;
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
//freopen("D://test.in", "r", stdin);
//freopen("D://test.out", "w", stdout);
int n;
cin>>n;
for(int i = 0; i < n; i++)
{
cin >> arr[i].endtime >> arr[i].val;
}
sort(arr, arr + n, cmp);
priority_queue <ll, std::vector<ll>, greater<ll> > PQ;
int len = 0;
for(int i = 0; i < n; i++)
{
if(arr[i].endtime > len)
{
PQ.push(arr[i].val);
++len;
}
else
{
if(arr[i].val > PQ.top())
{
PQ.pop();
PQ.push(arr[i].val);
}
}
}
ll ans = 0;
while(!PQ.empty())
{
ans += PQ.top();
PQ.pop();
}
cout<<ans<<'
';
return 0;
}