【Loj #10008. 「一本通 1.1 练习 4」家庭作业】题解

题目链接

题目

老师在开学第一天就把所有作业都布置了,每个作业如果在规定的时间内交上来的话才有学分。每个作业的截止日期和学分可能是不同的。例如如果一个作业学分为 101010,要求在 666 天内交,那么要想拿到这 101010 学分,就必须在第 666 天结束前交。

每个作业的完成时间都是只有一天。例如,假设有 7 次作业的学分和完成时间如下:
作业号 期限 学分
111 111 666
222 111 777
333 333 222
444 333 111
555 222 444
666 222 555
777 666 111

最多可以获得 151515 学分,其中一个完成作业的次序为 2,6,3,1,7,5,42,6,3,1,7,5,42,6,3,1,7,5,4,注意可能还有其他方法。

你的任务就是找到一个完成作业的顺序获得最大学分。

思路

按学分从大到小排序,优先放在最后的时间。

然后这是 \(O(n^2)\),会炸。

于是我们可以套个并查集。

Code

// Problem: #10008. 「一本通 1.1 练习 4」家庭作业
// Contest: LibreOJ
// URL: https://loj.ac/p/10008
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define int long long
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<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M
//#define mo
//#define N
struct node
{
	int t, v; 
}a[1000010]; 
int n, m, i, j, k; 
int f[700010]; 

bool cmp(node x, node y)
{
	return x.v>y.v; 
}

int dfs(int x)
{
	if(f[x]==x) return x; 
	return f[x]=dfs(f[x]); 
}

signed main()
{
//	freopen("tiaoshi.in", "r", stdin); 
//	freopen("tiaoshi.out", "w", stdout); 
	n=read(); 
	for(i=1; i<=700000; ++i) f[i]=i; 
	for(i=1; i<=n; ++i)
		a[i].t=read(), a[i].v=read(); 
	sort(a+1, a+n+1, cmp); 
	for(i=1; i<=n; ++i)
	{
		j=dfs(a[i].t); 
		if(j) k+=a[i].v, f[j]=f[j-1]; 
	}
	printf("%lld", k); 
	return 0; 
}

posted @ 2021-12-04 22:43  zhangtingxi  阅读(64)  评论(0编辑  收藏  举报