题目链接:R - Zyn的超能力 | SDUT OnlineJudge
Description
Zyn 需要能量提高自己的超能力,有两种能量存在:超级能量和小能量。对于超级能量,Zyn 绝对不可以错过,而且努力的 Zyn 希望得到更多的小能量。
但是 Zyn 每天最多可以获得 k 次能量,而且每个能量都会在第 xi 天后消失,Zyn 希望你可以帮助他求出得到的小能量的最多数量。
Input
第一行包含三个正整数 n,m,k (1≤n,m≤10e6,1≤k≤10e7)(1≤n,m≤10e6,1≤k≤10e7) 表示超级能量,小能量和每天最多可以获得能量的个数。
第二行包含 n 个整数,表示第 i 个超级能量会在第 xi (0≤i<=10e7)(0≤xi≤10e7) 天消失。
第三行包含 m 个整数,表示第 i 个小能量会在第 xi (0≤i≤10e7)(0≤xi≤10e7) 天消失。
Output
如果不能获得全部超级能量,输出"Zyn!"(不含引号),否则输出可以获得的最多的小能量的数量。
思路:我们可以开一个c数组先把从第0天到第1e7天全赋值为k,让他每天都得到k次。然后因为我们取到所有的超级能量,因此先处理超级能量。先从最大的那一天开始向前遍历,如果第i天得到该能量,那么c[i]--。处理结束后,就从前面的一天向后遍历小能量。
参考代码及注释:
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
ll n ,m,k;
ll a[1000007],b[1000007],c[10000007];
int main(){
scanf("%lld %lld%lld",&n,&m,&k);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=1;i<=m;i++)scanf("%lld",&b[i]);
for(int i=0;i<=1e7;i++)c[i]=k;
sort(a+1,a+n+1);
sort(b+1,b+m+1);
ll g=a[n];//将g先变为超级能量最后消失的那天
for(ll i=n;i>=1;i--){
g=min(a[i],g);//取被处理过的g以及a[i]之间的最小值,防止出现c[a[i]]已经清零的情况
c[g]--;//得到超级能量,那天得到小能量的次数减一
if(c[g]==0)//如果为0就一直遍历到不为0时
{
while(g>=0&&c[g]==0){g--;
if(g<0&&i>=2){//如果给g<0代表第0天的次数也用完了,如果此时还有超级能量,那就不能完全获得
printf("Zyn!");
return 0;
}
}
}
}
ll d=0; ll cnt=0;//cnt为小能量获取数量,d为第几天
for(int i=1; i<=m; i++) {
if(c[d]>0&&d<=b[i]) {//如果d是在b[i]之前的天数,同时那天还有得到能量的次数
c[d]--;//次数减一
cnt++;//小能量加1
if(c[d]==0) {//如果为0,遍历到不为0的天数
while(c[d]==0)d++;
}
}
else if(d<=b[i]) {//如果在那之前,但次数为0,则向后遍历
while(c[d]==0)
d++;
if(d>b[i])continue;//如果这个d大于b[i]了,则能量消失
else {
c[d]--;
cnt++;
if(c[d]==0) {
while(c[d]==0&&d<=m)d++;
}
}
}
//剩下的情况就是这个d大于b[i]了,则能量消失,不做讨论
}
printf("%lld",cnt);
}