R - Zyn的超能力

题目链接: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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值