[CF1251D] Salary Changing - 二分,贪心
Description
确定一个长度为 (n) 的数列,第 (i) 个数满足约束 (x_i in [l_i,r_i]),最大化中位数
Solution
二分答案 (mid),那么元素被分为三类
- (r<mid),必须要立即处理掉(填对应的 (l)),如果这部分已经超过 ([n/2]) 个,则无解
- (l < mid),这部分贪心处理,小于 (mid) 的那 ([n/2]) 个数剩下的地方尽可能填这部分中较小的 (l)
- 剩余的,填 (mid) 和 (l) 的 (max)
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t, n, s;
const int N = 1e6 + 5;
int l[N], r[N], x[N];
bool check(int mid)
{
int cost = 0;
int cnt = 0;
for (int i = 1; i <= n; i++)
x[i] = 0;
for (int i = 1; i <= n; i++)
if (r[i] < mid)
x[i] = l[i], ++cnt, cost += x[i];
if (cnt > n / 2)
return false;
for (int i = 1; i <= n && cnt < n / 2; i++)
if (x[i] == 0 && l[i] < mid)
x[i] = l[i], ++cnt, cost += x[i];
for (int i = 1; i <= n; i++)
if (x[i] == 0)
x[i] = max(mid, l[i]), cost += x[i];
return cost <= s;
}
void solve()
{
cin >> n >> s;
for (int i = 1; i <= n; i++)
cin >> l[i] >> r[i];
vector<pair<int, int>> vec;
for (int i = 1; i <= n; i++)
vec.push_back({l[i], r[i]});
sort(vec.begin(), vec.end());
for (int i = 1; i <= n; i++)
tie(l[i], r[i]) = vec[i - 1];
int left = 1, right = 1e9 + 1;
while (left < right)
{
int mid = (left + right) / 2;
if (check(mid))
left = mid + 1;
else
right = mid;
}
cout << left - 1 << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin >> t;
while (t--)
solve();
}