题意
有 n n n 项作业,每项作业有期限和学分,每完成一项作业时间代价为 1 1 1(占用一个时间点),问你最多能获得多少学分?
思路
我们要让学分尽可能的大,也就要优先处理学分多的作业,将每项作业从大到小排序。
随后枚举每项作业,枚举其时间限制内的所有时间点,如果还有没被占用的时间,也就再此时写我们此时枚举到的作业,将此时标记为被占用,将其计入答案。如果时间限制内所有节点都被占用,也就没有办法再找到一个时间点来写作业了,不用处理。
但是如果我们将这份代码交上去会 T L E TLE TLE,所以我们考虑进行优化。
如果在时间限制内没有时间点来写作业,也就代表如果有某个作业的时间限制小于当前时间限制,也没有时间点来写作业了。我们记录一个 l a s t last last 值,在 1 1 1 到 l a s t last last 之间没有一个时间节点还可以写作业。在每次判断的时候,如果时间限制内所有节点都被占用,将 l a s t last last 更新为它与目前时间限制的最大值。
代码
#include<bits/stdc++.h>
using namespace std;
struct node{
int t,w;
bool operator<(const node &W)const{
return w>W.w;
}
}a[1000001];
bool vis[1000001];
int main()
{
int n,ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d %d",&a[i].t,&a[i].w);
sort(a+1,a+n+1);
int last=0;
for(int i=1;i<=n;i++)
{
int cnt=a[i].t;
if(cnt<last) continue;
while(vis[cnt]&&cnt>0) cnt--;
if(cnt>0)
{
vis[cnt]=1;
ans+=a[i].w;
}
else last=max(last,a[i].t);
}
printf("%d\n",ans);
return 0;
}