[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();
}

相关文章:

  • 2021-09-11
  • 2022-12-23
  • 2022-12-23
  • 2021-09-22
  • 2022-03-01
  • 2021-10-31
  • 2021-12-28
  • 2021-09-04
猜你喜欢
  • 2022-12-23
  • 2021-12-04
  • 2021-09-21
  • 2022-12-23
  • 2021-11-24
  • 2021-07-20
  • 2022-12-23
相关资源
相似解决方案