【贪心】家庭作业 【链表优化】
题目描述
老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10,要求在6天内交,那么要想拿到这10学分,就必须在第6天结束前交。
每个作业的完成时间都是只有一天。例如,假设有7次作业的学分和完成时间如下:
老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10,要求在6天内交,那么要想拿到这10学分,就必须在第6天结束前交。
每个作业的完成时间都是只有一天。例如,假设有7次作业的学分和完成时间如下:
每个作业的完成时间都是只有一天。例如,假设有7次作业的学分和完成时间如下:
老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为10,要求在6天内交,那么要想拿到这10学分,就必须在第6天结束前交。
每个作业的完成时间都是只有一天。例如,假设有7次作业的学分和完成时间如下:
输入
第一行一个整数N,表示作业的数量;
接下来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
分析:
优先选择分高的,所以先根据分数从高到低排序,然后预处理链表为:每一天指向最近的空闲的前一天
然后遍历一次 若可以 则更新链表
代码:
#include <bits/stdc++.h> using namespace std; const int maxn = 1000005; int pre[maxn]; bool vis[maxn]={0}; struct node{ int d,v; }a[maxn]; int cmp(node x,node y) { if(x.v!=y.v) return x.v>y.v; else return x.d>y.d; } inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int findfa(int x) { if(!vis[x]) return x; else return pre[x] = findfa(pre[x]); } int main(){ int n; n = read(); for(int i=0;i<n;i++){ a[i].d = read(); a[i].v = read(); } sort(a,a+n,cmp); for(int i=1;i<=700000;i++) pre[i] = i-1; int ans = 0; int pre_pos; for(int i=0;i<n;i++) { pre_pos = findfa(a[i].d); if(pre_pos==0) continue; else { vis[pre_pos] = 1; ans+=a[i].v; } } printf("%d\n",ans); return 0; }