P9559 [SDCPC2023] D-Fast and Fat

发布时间 2023-08-22 19:33:51作者: One_JuRuo

思路

直接做比较难,考虑二分答案,所以我们需要想出一种时间复杂度还行的方法检查答案是否合格。

假设目前二分的答案是 \(x\),那么速度低于 \(x\) 必然需要别人背。

那么,自然而然地想到将所有人分成两部分,那么速度低于 \(x\) 中的所有人应当优先满足较重的,如果优先满足较轻的,就可能导致较重的无法被满足。

同时,速度低于 \(x\) 的人中,最重的,应该用速度和体重之和最大的人来满足,如果满足不了,这个答案就肯定无法满足,如果能满足就可以继续看下一组人。

具体实现可以用优先队列排序,每次取最大的。

AC 代码

#include<bits/stdc++.h>
using namespace std;
struct node{int v,w;}t[100005];
inline bool cmp(node a,node b){return a.v<b.v;}
int T,n,l,r,mid,ans;
inline bool check(int x)
{
	priority_queue<int>l,r;
	for(int i=1;i<=n;++i)
	{
		if(t[i].v>=x) r.push(t[i].w+t[i].v);//分成两个部分,速度满足条件的要看速度和体重之和
		else l.push(t[i].w);//速度不满足的只看体重
	}
	while(!l.empty()&&!r.empty())
		if(r.top()-l.top()>=x) l.pop(),r.pop();//每次看最大的一组人是否满足条件
		else return 0;
	return (l.empty());//如果最后剩的是速度低的人也不满足条件
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;++i) scanf("%d%d",&t[i].v,&t[i].w);
		sort(t+1,t+n+1,cmp),l=0,r=1000000000,ans=0;
		while(l<=r)//二分答案
		{
			mid=l+r>>1;
			if(check(mid)) l=mid+1,ans=mid;
			else r=mid-1;
		}
		printf("%d\n",ans);
	}	
}