CF1251D Salary Changing

CF1251D Salary Changing

按照左端点从小到大排序,然后二分答案x贪心判断。

倒着扫

最优情况是(n/2+1)个x,其余数取左端点。

首先,如果这个节点的右端点比x大并且还没取满n/2+1个,优先把这个人的工资设成x,因为它的左端点一定没有l更小的优。

否则直接取左端点。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=200005;
const int inf=1e15;
int T,n,s,l,r,ans;
inline int max(const int &a,const int &b) {
    return a>b?a:b;
}
inline int min(const int &a,const int &b) {
    return a<b?a:b;
}
struct node {
    int l,r;
}a[N];
bool cmp(const node &a,const node &b) {
    return a.l<b.l;
}
bool check(int x) {
    int sum=n/2+1,total=s;
    for(int i=n;i>=1;--i) {
        if(a[i].r>=x&&sum) {
            total-=max(x,a[i].l);
            --sum;
        } else {
            total-=a[i].l;
        }
    }
    return (!sum)&&(total>=0);
}
signed main() {
    scanf("%lld",&T);
    while(T--) {
        l=inf,r=0;
        scanf("%lld%lld",&n,&s);
        for(int i=1;i<=n;++i)
            scanf("%lld%lld",&a[i].l,&a[i].r),l=min(l,a[i].l),r=max(r,a[i].r);
        sort(a+1,a+n+1,cmp);
        while(l<=r) {
            int mid=(l+r)>>1;
            if(check(mid))ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
上一篇:luogu_P3937 Changing


下一篇:mysql子查询慢的问题