第十四届蓝桥杯省赛C++编程题解;数字游戏

2023-05-18 09:17:59    动态资讯   

老师给出了一组数,要求小蓝对这组数进行调整,调整的规则如下:

1. 1次,从这组数中选出一个最小的数,把它调整为和第二小的数一样大;

2. 2次,再从这组数中选出一个最大的数,把它调整为和第二大的数一样大;

3. 重复执行12步骤;

4. 当这组数中所包含的不同的数少于3个时,结束调整。

 

现在给定了一组数,请帮小蓝编写程序计算出总共的调整次数,以及调整结束时这组数中的最小数和最大数。

 

1

当这组数是 2 2 2 2时,这组数中所包含的不同的数少于3个(只有2这一种数),无需调整,最后输出:

0 2 2

 

2

当这组数是 1 3 4 2时,调整过程如下:

1. 先将这组数中最小的数1,改成2,这组数变为:2 3 4 2

2. 再将这组数中最大的数4,改成3,这组数变为:2 3 3 2

这时,这组数中只包含23两个数了,满足规则4,调整结束,总共调整了2次,故最后输出:

2 2 3

 

【输入描述】

第一行输入一个正整数N3N1000000),表示这组数中数的个数

第二行输入N个正整数(1≤正整数≤1000000),正整数之间用一个空格隔开

【输出描述】

输出一行,包含三个整数,分别是总的调整次数、调整结束时的最小值和最大值,整数之间用一个空格隔开

 

【样例输入】

4

1 3 4 2

【样例输出】

2 2 3

 

分析:

考察桶计数+双指针算法。

#include<iostream>
using namespace std;
int a[1000005],n,t,sum,ans,lsum,rsum;
int main()
{
  scanf("%d",&n);
  for(int i=1;i<=n;i++)
  {
    scanf("%d",&t);
    if(a[t]==0)sum++;//sum记录数字种数 
    a[t]++;//a[t]存储数字t的个数 
  }
  int l=0,r=1000000;
  while(a[l]==0)l++;//找出最小值的位置 
  while(a[r]==0)r--;//找出最大值的位置 
  while(sum>2)
  {
    //考虑到运算效率,只要sum>2直接消掉最大/小值中数量较少的一位 
    if(a[l]<a[r])//消除所有l 
    {
      t=a[l];
      a[l]=0;
      a[r]-=t;
      ans+=2*t;
      sum--;
      while(a[l]==0) l++;
    }
    else if(a[l]>a[r])//消除所有r 
    {
      t=a[r];
      a[r]=0;
      a[l]-=t;
      ans+=2*t;
      sum--;
      while(a[r]==0) r--;
    }
    else//如果两者数量相同,则一起消除 
    {
      t=a[l];
      a[l]=a[r]=0;
      ans+=2*t;
      while(a[l]==0)l++;
      sum--;
      if(sum==2)//特判,如果消完左边sum就剩下2了,就不能消右边,直接得出结果 
      {
        ans-=1;
        break;
      }
      while(a[r]==0)r--;
      sum--;
    }
  }
  printf("%d %d %d",ans,l,r);
  return 0;
}