P4343 [SHOI2015]自動刷題機
阿新 • • 發佈:2021-09-17
找最大值:二分到一個n的值t,然後根據日誌檢查在t的情況下能切幾題,如果滿足切的題目數>=k,那麼所有比t小的值都能夠使得切題數>=k,此時可能可以找到n的最大值,因為如果不存在一個t能使切題數正好是k的話,找到的值是最大的能夠使切題數>k的值
找最小值:二分到一個n的值t,如果滿足切的題目數<=k,那麼所有比t大的值都能夠使得切題數<=k,此時可能可以找到n的最小值,因為如果不存在一個t能使切題數正好是k的話,找到的值是最小的能夠使切題數<=k的值
複雜度:\(O(l \log N)\), 其中N是n的二分範圍大小,一開始取得範圍很大(\(\log N\)
另外還需要注意的就是,先找最小值,找到以後需要特判一下二分出來的最小值能不能讓切題數正好是k,不能就直接輸出-1
#include<iostream> #include<cstring> using namespace std; const int N = 100010; #define LL long long LL a[N]; int ll, k; LL check(LL x){ LL cnt = 0; int res = 0; for(int i = 0; i < ll; i ++){ cnt = max(cnt + a[i], (LL) 0); if(cnt >= x) res ++, cnt = 0; } return res; } int main(){ cin >> ll >> k; for(int i = 0; i < ll; i ++) cin >> a[i]; LL l = 1, r = (LL) 1 << 41; while(l < r){ LL mid = l + r >> 1; if(check(mid) <= k) r = mid; // 如果切題的個數滿足<=k else l = mid + 1; } if(check(l) != k){ puts("-1"); return 0; } cout << l << ' '; l = 1, r = (LL) 1 << 41; while(l < r){ LL mid = l + r + 1 >> 1; if(check(mid) >= k) l = mid; else r = mid - 1; } cout << l; return 0; }