链接
https://nanti.jisuanke.com/t/41406
题意
有 $n$ 个水池,每天从水最多的水池取出一升水放入水最少的水池。
问 $k$ 天后水最多的水池和水最少的水池的差。
思路
可以发现所有水池的水量都趋于平均值移动。
因此只要二分确定最大值和最小值即可。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include <bits/stdc++.h> #define SZ(x) (int)(x).size() #define ALL(x) (x).begin(),(x).end() #define PB push_back #define EB emplace_back #define MP make_pair #define FI first #define SE second using namespace std; typedef double DB; typedef long double LD; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef vector<int> VI; typedef vector<PII> VPII;
const int N=5e5+5; int n,k,a[N]; bool check1(int mid) { LL ret=0; for(int i=n;a[i]>mid;i--) ret+=a[i]-mid; return ret<=k; } bool check2(int mid) { LL ret=0; for(int i=1;a[i]<mid;i++) ret+=mid-a[i]; return ret<=k; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); while(cin>>n>>k) { LL sum=0; for(int i=1;i<=n;i++) { cin>>a[i]; sum+=a[i]; } sort(a+1,a+1+n); int ll,rr; if(sum%n==0) ll=rr=sum/n; else ll=sum/n,rr=ll+1; int l=rr,r=a[n]; while(l<r) { int mid=l+r>>1; if(check1(mid)) r=mid; else l=mid+1; } int res=l; l=a[1],r=ll; while(l<r) { int mid=l+r+1>>1; if(check2(mid)) l=mid; else r=mid-1; } cout<<res-l<<'\n'; } return 0; }
|