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
",ans);
	}
	return 0;
}
路漫漫其修远兮,吾将上下而求索
原文地址:https://www.cnblogs.com/zzctommy/p/12416457.html