山东理工大学第十五届ACM程序设计竞赛 R - Zyn的超能力

Description

Zyn 需要能量提高自己的超能力,有两种能量存在:超级能量和小能量。对于超级能量,Zyn 绝对不可以错过,而且努力的 Zyn 希望得到更多的小能量。

但是 Zyn 每天最多可以获得 k 次能量,而且每个能量都会在第 xi​ 天后消失,Zyn 希望你可以帮助他求出得到的小能量的最多数量。

Input

第一行包含三个正整数 n,m,k (1≤n,m≤106,1≤k≤107) 表示超级能量,小能量和每天最多可以获得能量的个数。

第二行包含 n 个整数,表示第 i 个超级能量会在第 xi​ (0≤xi​≤107) 天消失。

第三行包含 m 个整数,表示第 i 个小能量会在第 xi​ (0≤xi​≤107) 天消失。

Output

如果不能获得全部超级能量,输出"Zyn!"(不含引号),否则输出可以获得的最多的小能量的数量。

Sample

Input 

3 4 2
0 2 3
1 1 2 5

5 3 2
0 0 0 1 1
1 1 2

Output 

4

Zyn!

Hint

题目样例为两组,由于 OJ 不支持多样例所以用回车分隔开。

样例一:可以在 44 天内获得所有小能量,

  • 第 00 天:22 个超级能量
  • 第 11 天:22 个小能量
  • 第 22 天:11 个超级能量 + 11 个小能量
  • 第 33 天:11 个小能量

总共获得 44 个小能量(33 个超级能量全部获得)

样例二:没用任何一种方法可以获得全部超级能量,输出"Zyn!"(不含引号)

考试时的思路完全错了,想得就是从前向后遍历,如果今天的超近能量大于k,则判断一下ans+k与今日超级能量的大小关系;

错误代码(当然也犯了一个致命错误,应该从0开始)

#include
using namespace std;
const int N=1e7+100;
#define endl '\n'
#define ll long long
int n,m,k;
int supper[N],small[N];
int cnt;
int cnt1[N];
int cnt2[N];
int ans;
int M;
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++)
	{
	scanf("%d",&supper[i]);
	cnt1[supper[i]]++;
	M=max(M,supper[i]);
	}
	for(int i=1;i<=m;i++)
	{
	scanf("%d",&small[i]);
	cnt2[small[i]]++;
	M=max(M,small[i]);	
	}
	while(1)
	{
	if(cnt>M)
	break;
	int num=k;
	if(cnt1[cnt]>k)
	{
	if(cnt1[cnt]>k+ans)
	{
	printf("Zyn!");
	return 0;
	}
	else
	{
	 if(ans>=cnt1[cnt])
	 ans-=cnt1[cnt];
	 else 
	 {
	 ans=0;
	 num=num+ans-cnt1[cnt];
	 }
	}
	}
	else
	num-=cnt1[cnt];
	if(num>=cnt2[cnt])
	{
		num-=cnt2[cnt];
		ans+=cnt2[cnt];
	}
	else
	ans+=num;
	cnt++;
	}
	printf("%d\n",ans);
	return 0;
}

根据截止时间的性质,按照截止时间从大到小的顺序依次枚举超级能量,判定每天剩余小能量的 数量,然后根据当天小能量的数量枚举可能的最大数量

#include
using namespace std;
const int N=1e7+10;
#define inf 0x3f3f3f3f
int  a[N],b[N];
int n,m,k;
int maxa,maxb;
int cnt;
int ans;
int main()
{
    cin>>n>>m>>k;
    for(int i=0;i>x;
        a[x]++;
        maxa=max(maxa,x);
    }
    for(int i=0;i>x;
        b[x]++;
        maxb=max(maxb,x);
    }
    for(int i=maxa;i>=0;i--)
    {
        if(a[i]>k)
        {
         cnt+=a[i]-k;
         a[i]=k;
        }
        else if(a[i]=k-a[i])
            {
                cnt-=(k-a[i]);
                a[i]=k;
            }
        }
    }
    if(cnt)//没有拿全超级能量
    {
        cout<<"Zyn!";
        return 0;
    }
    cnt=0;
    for(int i=maxb;i>=0;i--)
    {
       b[i]+=cnt;
       cnt=0;
       if(b[i])
       {
         int can=k-a[i];
         if(can>=b[i])
         {
            ans+=b[i];
            b[i]=0;
         }
         else
         {
            ans+=can;
            b[i]-=can;
            cnt=b[i];
            b[i]=0;
         }
       } 
    }
    cout<

你可能感兴趣的:(数学建模)