说在正文前: ZZSZOI是由ZZSZ举办的,旨在让ZZSZ机房中的人受苦提高代码水平的模拟赛,赛制为OI赛制,共四道题,难度与CSP-S相当。
1.家庭作业(homework)4174. 家庭作业 - AcWing题库
算法:贪心
思路一:按天排序,用一个数组维护已经取到的作业编号(学分)。扫描每一天时先加上该天的所有学分,如果作业数量(即加上该天所有作业之后数组内元素的个数)大于天数(即能做多少作业),那么就将已在数组中的作业中学分最小的选择不写,将它踢出数组。最后在数组中的作业的总学分便是答案。
代码实现(该思路用优先队列priority_queue+O2优化可以拿满分,用数组模拟加sort或优先队列不加O2能拿80分,下方给的是80分代码)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int N=1e6+10;
const int M=7e5+10;
int n;
struct node{
int a;
long long b;
}hw[N];
bool cmp(node x,node y)
{
if(x.a==y.a) return x.b<y.b;
else return x.a<y.a;
}
long long sum[N];
int w[M];
int s[N];
int vis[M];
int main()
{
// freopen("homework.in","r",stdin);
// freopen("homework.out","w",stdout);
scanf("%d",&n);
int t=1;
for(int i=1;i<=n;++i)
{
scanf("%d%lld",&hw[i].a,&hw[i].b);
t=max(t,hw[i].a);
}
sort(hw+1,hw+n+1,cmp);
for(int i=1;i<=n;++i)
{
sum[hw[i].a]=sum[hw[i-1].a]+hw[i].b;
w[hw[i].a]=w[hw[i-1].a]+1;
vis[hw[i].a]=1;
}
for(int i=1;i<=t;++i) if(!vis[i]) w[i]=w[i-1];
long long ans=0;
int l=1,r=0;
for(int i=1;i<=t;++i) if(!vis[i]) sum[i]=sum[i-1];
for(int i=1;i<=t;++i)
{
if(!vis[i]) continue;
for(int j=w[i-1]+1;j<=w[i];++j) s[++r]=hw[j].b;
ans+=sum[i]-sum[i-1];
if(r-l+1>i)
{
sort(s+l,s+r+1);
int tem=r-l+1-i;
while(tem--)
{
long long mew=s[l];
l++;
ans-=mew;
}
}
}
printf("%lld",ans);
// fclose(stdin);
// fclose(stdout);
return 0;
}
(其实有很多另外的贪心实现思路和思路一相似,共同点是都是按天排序)
思路二:按作业