老师给出了一组数,要求小蓝对这组数进行调整,调整的规则如下:
1. 第1次,从这组数中选出一个最小的数,把它调整为和第二小的数一样大;
2. 第2次,再从这组数中选出一个最大的数,把它调整为和第二大的数一样大;
3. 重复执行1、2步骤;
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
这时,这组数中只包含2、3两个数了,满足规则4,调整结束,总共调整了2次,故最后输出:
2 2 3
【输入描述】
第一行输入一个正整数N(3≤N≤1000000),表示这组数中数的个数
第二行输入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;
}