题目链接:https://vijos.org/d/ybttg/p/5c24b83ff41362c9e19126c3
时间限制:1000 ms 内存限制:512 MiB
题目描述
老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为 10 10 10,要求在 6 6 6天内交,那么要想拿到这 10 10 10学分,就必须在第 6 6 6天结束前交。
每个作业的完成时间都是只有一天。例如,假设有 7 7 7次作业的学分和完成时间如下:
作业号 | 期限 | 学分 |
---|---|---|
1 | 1 | 6 |
2 | 1 | 7 |
3 | 3 | 2 |
4 | 3 | 1 |
5 | 2 | 4 |
6 | 2 | 5 |
7 | 6 | 1 |
最多可以获得
15
15
15学分,其中一个完成作业的次序为
2
,
6
,
3
,
1
,
7
,
5
,
4
2,6,3,1,7,5,4
2,6,3,1,7,5,4,注意可能还有其他方法。
你的任务就是找到一个完成作业的顺序获得最大学分。
输入格式
第一行一个整数 N N N,表示作业的数量;
接下来 N N N行,每行包括两个整数,第一个整数表示作业的完成期限,第二个数表示该作业的学分。
输出格式
输出一个整数表示可以获得的最大学分。保证答案不超过 C / C + + C/C++ C/C++的 i n t int int范围。
样例数据
样例输入
7
1 6
1 7
3 2
3 1
2 4
2 5
6 1
样例输出
15
限制与提示
对于 20 % 20\% 20%的数据, N ≤ 1 0 3 N \leq 10^3 N≤103;
对于 40 % 40\% 40%的数据, N ≤ 1 0 4 N \leq 10^4 N≤104;
对于 60 % 60\% 60%的数据, N ≤ 1 0 5 N \leq 10^5 N≤105;
对于 100 % 100\% 100%的数据, N ≤ 1 0 6 N \leq 10^6 N≤106,作业的完成期限均小于 7 × 1 0 5 7\times 10^5 7×105。
题解
题意:给你一些带有学分和时限的作业,在时限之内完成作业,就可以获得相应的学分,每个作业的完成时间都是只有一天,求能获得最大学分。
思路:我们先把作业按学分从大到小排个序。然后从第一份作业开始选择做与不做。如果在这一份作业的期限之前还有时间可以空闲,那就做这一份作业,在这里我们可以用一个优化,用一个链表f,f[i]指向f[i]之前的空闲时间。
Accepted Code:
/*
* @Author: lzyws739307453
* @Language: C++
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 5;
struct edge {
int t, v;
bool operator < (const edge &s) const {
return s.v < v;
}
}p[MAXN];
int fa[MAXN];
int find_fa(int v) {
if (!~fa[v])
return v;
return fa[v] = find_fa(fa[v]);
}
int main() {
int n, cnt = 0;
scanf("%d", &n);
memset(fa, -1, sizeof(fa));
for (int i = 0; i < n; i++)
scanf("%d%d", &p[i].t, &p[i].v);
sort(p, p + n);
for (int i = 0; i < n; i++) {
int x = find_fa(p[i].t);
if (x) {
fa[x] = find_fa(x - 1);
cnt += p[i].v;
}
}
printf("%d\n", cnt);
return 0;
}