Salary Changing
Thinking
這道題第一思路就是二分,模擬了一下樣例,感覺好像行於是就開始寫。
對於二分,我們一定是二分中位數是什麼,二分的邊界對我們來說是非常重要的,所以我們在二分前有必要確認我們的二分邊界,因爲一定有,所以我們對數組一遍,得到,同樣的,對數組一遍,得到,接下來我們就可以開始我們的二分了。
但是這道題的難點不是在二分思想上,而是函數有點難寫:
- 首先我們對每一個人的按照從小到大排序。
- 接下來,我們可以通過二分得到的人數量,如果這個二分值過大,直接返回false。
- 否則我們進行貪心的選值,記錄下這些點的,然後進行排序,優先選擇小的去補充我們所需的,但是還沒有選滿的。
- 接下來就是對於的進行貪心選,假設他的就選擇,否則的話就是選擇。
下面代碼中有更詳細的描述函數。
Coding
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
using 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;
}