题目链接:https://nanti.jisuanke.com/t/41406 思路:如果k的天数足够大,那么所有水池一定会趋于两种情况: ① 所有水池都是一样的水位,即平均水位 ② 最高水位的水池和最低水位的水池高
题目链接:https://nanti.jisuanke.com/t/41406
思路:如果k的天数足够大,那么所有水池一定会趋于两种情况:
① 所有水池都是一样的水位,即平均水位
② 最高水位的水池和最低水位的水池高度只相差一个高度,且最低水位一定是平均水位
如果k给了个限制:
我们当然需要先算出所有水池高度的平均值。
然后从低到高排序,二分小于平均值的水位,二分高于平均值的水位,
然后判断二分的预期值需要的天数是否小于等于k。然后二分找出最低水位的最大值,
最高水位的最小值,两者相减就是答案了。
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 #include <map> 6 #define rep(i,j,k) for(int i = (j); i <= (k); ++i) 7 #define per(i,j,k) for(int i = (j); i >= (k); --i) 8 #define rep__(i,j,k) for(int i = (j); i < (k); ++i) 9 #define per__(i,j,k) for(int i = (j); i > (k); --i) 10 #define inf 1e9 11 using namespace std; 12 typedef long long LL; 13 const int N = 500010; 14 15 int arr[N],k,n; 16 LL sum,ave; 17 18 bool check(int mid,int choice){ 19 int sum = 0; 20 if(choice == 1){ //大于平均值的 21 rep(i,1,n){ 22 if(arr[i] >= mid) break; 23 sum += (mid - arr[i]); 24 } 25 } 26 else{ //小于平均值的 27 per(i,n,1){ 28 if(arr[i] <= mid) break; 29 sum += (arr[i] - mid); 30 } 31 } 32 33 if(sum <= k) return true; 34 else return false; 35 } 36 37 int main(){ 38 39 while(~scanf("%d",&n)){ 40 sum = 0; 41 scanf("%d",&k); 42 rep(i,1,n){ 43 scanf("%d",arr + i); 44 sum += arr[i]; 45 } 46 47 sort(arr + 1,arr + 1 + n); 48 ave = sum / n; 49 50 int l_end,r_start; //低于平均值的最大水位,高于平均值的最小水位 51 l_end = ave; 52 sum % n == 0 ? r_start = ave : r_start = ave + 1; //是否能平分 53 54 int ans_1,ans_2; 55 int l = arr[1];//左边界 56 int r = l_end;//右边界 57 int mid; 58 while(l <= r){ 59 mid = (l + r) >> 1; 60 if(check(mid,1)){ 61 ans_1 = mid; 62 l = mid + 1; 63 } 64 else r = mid - 1; 65 } 66 67 l = r_start;//左边界 68 r = arr[n];//右边界 69 while(l <= r){ 70 mid = (l + r) >> 1; 71 if(check(mid,2)){ 72 ans_2 = mid; 73 r = mid - 1; 74 } 75 else l = mid + 1; 76 } 77 78 printf("%d\n",ans_2 - ans_1); 79 } 80 81 getchar();getchar(); 82 return 0; 83 }