D. Salary Changing(二分,前缀和,贪心,瞎搞)
生活随笔
收集整理的這篇文章主要介紹了
D. Salary Changing(二分,前缀和,贪心,瞎搞)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Salary Changing
Thinking
這道題第一思路就是二分,模擬了一下樣例,感覺好像行于是就開始寫。
對于二分,我們一定是二分中位數是什么,二分的邊界對我們來說是非常重要的,所以我們在二分前有必要確認我們的二分邊界,因為一定有∑i=1nli<=s\sum _{i = 1} ^ {n} l_i <= s∑i=1n?li?<=s,所以我們對lll數組sortsortsort一遍,得到left=lmidleft = l_{mid}left=lmid?,同樣的,對rrr數組sortsortsort一遍,得到right=rmidright = r_{mid}right=rmid?,接下來我們就可以開始我們的二分了。
但是這道題的難點不是在二分思想上,而是judgejudgejudge函數有點難寫:
- 首先我們對每一個人的salarysalarysalary按照rrr從小到大排序。
- 接下來,我們可以通過二分得到salaryl<=mid<=salaryrsalary_l <= mid <= salary_rsalaryl?<=mid<=salaryr?的人數量numnumnum,如果n<n/2+1n < n / 2 + 1n<n/2+1這個二分值過大,直接返回false。
- 否則我們進行貪心的選值,記錄下這些點的salarylsalary_lsalaryl?,然后進行排序,優先選擇小的去補充我們所需的salary<midsalary < midsalary<mid,但是還沒有選滿的。
- 接下來就是對于salary>=midsalary >= midsalary>=mid的進行貪心選,假設他的salaryl>xsalary_l > xsalaryl?>x就選擇salarylsalary_lsalaryl?,否則的話就是選擇xxx。
下面代碼中有更詳細的描述judgejudgejudge函數。
Coding
#include <bits/stdc++.h> #define mp make_pair #define pb push_backusing namespace std;typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii;const double pi = acos(-1.0); const double eps = 1e-7; const int inf = 0x3f3f3f3f;inline ll read() {ll f = 1, x = 0;char c = getchar();while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9') {x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return f * x; }const int N = 2e5 + 10;ll L[N], R[N], n, s, m;struct Node {int l, r;bool operator < (const Node & t) const {return r < t.r;} }a[N];bool judge(int x) {int p = lower_bound(R + 1, R + 1 + n, x) - R;int last = n - p + 1;//后面剩下了多少個數,if(last < m) return false;//如果沒辦法滿足 >= x的人數至少有n / 2 + 1個,那么x過大。vector<int> v;for(int i = p; i <= n; i++) v.pb(a[i].l);sort(v.begin(), v.end());int need = m - 1 - (p - 1);//前面選擇完任然不夠,所需要的。ll sum = L[p - 1];//一個前綴和數組,看main函數即可理解for(int i = 0; i < need; i++) {sum += v[i];if(v[i] > x) return false;//一定滿足前面的數 <= x,}for(int i = need; i < v.size(); i++) sum += max(x, v[i]);return sum <= s; }int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "r", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int _ = read();while(_--) {n = read(), s = read();m = n / 2 + 1;for(int i = 1; i <= n; i++) {a[i].l = read(), a[i].r = read();L[i] = a[i].l, R[i] = a[i].r;}sort(a + 1, a + 1 + n);sort(L + 1, L + 1 + n);sort(R + 1, R + 1 + n);int l = L[(n >> 1) + 1], r = R[(n >> 1) + 1];for(int i = 1; i <= n; i++)L[i] = a[i].l + L[i - 1];while(l < r) {int mid = l + r + 1 >> 1;if(judge(mid)) l = mid;else r = mid - 1;}printf("%d\n", l);}return 0; }總結
以上是生活随笔為你收集整理的D. Salary Changing(二分,前缀和,贪心,瞎搞)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 番泻叶的功效与减肥作用
- 下一篇: 刮油最狠的是哪四种减肥蔬菜