nyoj 2354 同時也是 codeforces Robin Hood(二分)
2354: 分班級
時間限制: 1 Sec 記憶體限制: 128 MB提交: 121 解決: 10
[提交][狀態][討論版]
題目描述
Zoro是一個有強迫症的人,他喜歡均衡。
17級的新生要開學了,起初所有班級是按照學生的來源地分的,各班人數非常不合理。於是老師要求Zoro來讓各班人數均衡一下。
由於學校系統陳舊,每次調換隻能是Zoro自己手動的把一個學生從一個班級拉到另外一個班級,由於Zoro有強迫症,他每次會找出班級人數最多的那個拉出一個人轉到一個人數最少的班級,而且每次操作,耗費一次許可權,而他的賬號只有k次許可權。老師最後會看所有班級人數差的最大值。
由於班級實在太多,Zoro要做完需要很長時間,你能不能幫助Zoro先計算出他工作完成後所有班級人數差的最大值報告給老師。
輸入
接下來一行n個整數 第i個數字代表第i個班級有ci個人。
(1<=n<=500000,0<=k<=1e9,0<= ci <=1e9)
輸出
樣例輸入
5 1
1 2 3 4 5
樣例輸出
2
思路:
1、一直在想二分差值,然後發現最小值和最大值的問題不是很好處理,一直在想一個科學的連續二分的方式去列舉出最小值和最大值。以一種二分套二分的方式去解,以失敗告終。
2、正解是這樣的:
首先得明確一點,初始時硬幣數比平均數少的人最終會增加k個硬幣,比平均數多的會減少k個硬幣,
所以根據這個先用二分求出最終最少的硬幣數,然後最用二分求出最終最多的硬幣數,然後相減就行了,明確這一點這題目差不多就出來了。。。
①因為時間越長(天數經過的越多),最大值就會越小,同理,最小值就會越大(所以這就是智障的去二分差值的理由?尼瑪本質是最大值最小值的變化好嘛,為毛要想到差值上去.......)那麼我們二分一個最小值,接下來二分一個最大值。
②判定二分的過程很簡單,對於列舉最小值的時候,如果需要的最少天數小於等於k,那麼就加大最小值,否則減小最小值即可。那麼二分列舉最大值的時候同理即可。
③問題的坑點在於維護上下界。對於總值:sum,如果sum%n==0,那麼最小值的上界就是sum/n,最大值的下界也是sum/n.當sum%n!=0的時候,最小值的上界還是sum/n,但是最大值的下界應該是sum/n+1.這裡被坑了......................
這個從最大的拿東西給最小的,不是列舉差值。。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 5e5 + 5;
typedef long long ll;
ll a[maxn], n, k;
int check(ll x) //判斷以這個x為最小的天數,需要多少天
{
ll res = 0;
for(int i = 1; i <= n; i++)
{
if(a[i] < x) res += x-a[i]; //比他小, 就說明這些都要得到1,最終達到最小的天
}
return res <= k;
}
int check2(ll x)
{
ll res = 0;
for(int i = 1; i <= n; i++)
{
if(a[i] > x) res += a[i]-x; //比他大, 就往外給,最終到達最大的天
}
return res <= k;
}
int main()
{
scanf("%lld%lld", &n, &k);
ll sum = 0;
for(int i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
sum += a[i];
}
ll limit = sum / n;
ll limit2 = limit;
if(sum%n) limit2++; //
ll ansx = 0, ansy = 0;
ll l = 1, r = limit, mid; //mid 表示 最大或者最小能夠到達的值
while(l <= r)
{
mid = (l+r)/2;
if(check(mid))
{
ansx = mid;
l = mid + 1;
}
else
r = mid - 1;
}
l = limit2;
r = sum;
while(l <= r)
{
mid = (l+r)/2;
if(check2(mid))
{
ansy = mid;
r = mid - 1;
}
else
l = mid + 1;
}
printf("%lld\n", ansy-ansx);
return 0;
}
相關文章
- android studio的一個方便的技能,同時他也是坑Android
- 電影Robin Hood和應用程式Robinhood出資5萬美元在動漫展舉行加密貨幣尋寶活動加密
- 世界上最優秀的程式設計師同時也是活得最快樂的人程式設計師
- ubuntu linux 修改socket最大連線數,同時也是檔案最大開啟數UbuntuLinux
- Oh, my goddess nyojGo
- 《糖豆人》Steam銷量超700萬,同時也是下載最多的PS會免遊戲遊戲
- Codeforces Round #361 (Div. 2) C 二分
- Codeforces Round #321 (Div. 2) B 二分
- Codeforces 484B Maximum Value(排序+二分)排序
- codeforces448D Multiplication Table(二分答案)
- Under the Hood: NaN of JavaScriptNaNJavaScript
- nyoj 8 一種排序排序
- NYOJ--字首式計算
- Codeforces2014E Rendez-vous de Marian et Robin(分層圖最短路)
- Codeforces Round #361 (Div. 2) D RMQ+二分MQ
- Codeforces Round #336 (Div. 2) C 二分+dp
- NYOJ--重建二叉樹二叉樹
- NYOJ 480 Fibonacci Again!AI
- Round-robin 演算法演算法
- Round Robin演算法概述演算法
- CodeForces 887 E. Little Brother(計算幾何+二分)
- 【二分,三分】Codeforces Round #403 The Meeting Place Cannot Be Changed
- Codeforces Round #360 (Div. 2) C DFS判斷二分圖
- Codeforces Round #316 (Div. 2) D DFS+vector+二分
- 50、abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?synchronized
- CF24E 二分(應注意二分什麼和二分時的處理細節)
- 同時使用:gitlab & githubGitlabGithub
- 快捷鍵-同時寫多行
- NYOJ 1409 快速計算【矩陣連乘】矩陣
- 耗時6小時的同花順面試面試
- 【PostgresSQL】同時更新兩個表SQL
- 遍歷List 同時 remove 元素REM
- linux 同時殺多程式Linux
- Redhat Linux bind round-robin配置的探討RedhatLinux
- ORACLE臨時表和SQLSERVER臨時表異同OracleSQLServer
- 網盤也是一種儲存 搜尋也是一種計算
- Reqman,一個可以快速幫助後端工程師進行api測試的工具,同時也是一個基於nodejs的爬蟲工具。後端工程師APINodeJS爬蟲
- 奧運也是IT的賽場