标签:若是 答案 过程 return efi sort unsigned 等于 操作
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6383
百度之星的比赛题目,这道题里面定义了一个稳定数列,数列的定义如下:
1. 数组里面的元素都是非负整数。
2. 数组里面最大的元素跟最小的元素的差值不超过 1。
然后输入一个数列,每次采取+1、-2的策略,问在可以达到稳定数列的情况下,最小值的最大值为多少。
可以证明,最后的-2,+1的数组肯定可以变成稳定数组。因为我们每次的操作相当于把两个数的和减一,两次就是每个数-1.(a-2,b+1, a+1,b-2)。最后肯定可以变成01这样的数组,就是稳定数组。在变化的过程有稳定数组的存在。说明我们就可以求的答案。
这样可以采取二分法去实现,二分枚举。mid左边的进行+1,右边的-2,判断左边的操作次数与右边的操作次数,若是右边的大于等于左边的,说明答案可能存在mid往上的某一个数,反之亦然。代码如下:
1 //#include<bits/stdc++.h> 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 7 #define e exp(1) 8 #define pi acos(-1) 9 #define mod 1000000007 10 #define inf 0x3f3f3f3f //0011_1111_0011_1111_0011_1111_0011_1111 11 #define ll long long 12 #define ull unsigned long long 13 #define mem(a,b) memset(a,b,sizeof(a)) 14 int gcd(int a,int b){return b?gcd(b,a%b):a;} //最大公约数 15 //数组肯定可以达到稳定状态,因为+1、-2肯定可以使值减小1,所以到最后变成01串,肯定可以稳定 16 int a[300005]; 17 int main() 18 { 19 int T;scanf("%d",&T); 20 while(T--) 21 { 22 int n;scanf("%d",&n); 23 for(int i=0; i<n; i++) 24 { 25 scanf("%d",&a[i]); 26 } 27 sort(a,a+n); 28 int l=0,r=1e8; 29 int ans=0; 30 while(l<=r) 31 { 32 ll x=0,y=0; //x记录加一的次数,y记录减二的次数 33 int mid=(l+r)>>1; //取中点 34 for(int i=0; i<n; i++) //比中值小的加一,加差值那么多次,比中值大的减二,减差值除以二的次数 35 { //在可以稳定的前提小去向中值靠拢 36 if(mid>a[i])x+=mid-a[i]; 37 if(mid<a[i])y+=(a[i]-mid)/2; 38 } 39 if(x<=y) //如果加的次数小于减的次数,说明答案可能存在mid往上的某一个数,反之亦然 40 { 41 ans=max(ans,mid); 42 l=mid+1; 43 } 44 else r=mid-1; 45 } 46 printf("%d\n",ans); 47 } 48 return 0; 49 }
标签:若是 答案 过程 return efi sort unsigned 等于 操作
原文地址:https://www.cnblogs.com/huhusw/p/9600048.html