老师给出了一组数,要求小蓝对这组数进行调整,调整的规则如下:
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; }