Atcoder 700 Worst Case 贪心+二分

题意:两个1,2,3,....inf的集合A,B. 从两个集合中各选一个数(a,b)的得分为a*b.
Q次询问,每次询问(a,b),[表示分别选中a,b].问从剩下的两个集合中最多能选出多少对(x,y)使得x*y<a*b  
Q<=100. 1<=a,b<=1e9.


当a<b
1,2,3,....a-1,a,a+1.....
1,2,3..C.............b,b+1......

(a+1)*(b+1)>ab , a<b时 (a-i)*(b+i)=ab+ai-bi-i*i < ab 所以让[1..a-1]和[b+1...]匹配.
[a+1..]这部分显然只能在b之前匹配 并且也是第i小的第i大匹配.

二分一个c 要找到 max(i*(a+c-i+1))[i=1..c] 中的最大值是否<ab 

因为是二次函数 在极点附近枚举一下即可.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll Q,a,b;
bool check(ll c)
{
	//f[x]=-x^2+(a+c+1)*x 
	ll A=-1,B=(a+c+1);
	ll po=-B/(2ll*A);
	//cout<<po<<'\n';
	for(ll i=max(1ll,po-500);i<=min(c,po+500);i++)
	{
		if(i*(a+c-i+1)>=a*b)
			return false;
	}
	return true;
}

int main()
{	
	cin>>Q;
	while(Q--)
	{
		cin>>a>>b;
		if(a>b)
			swap(a,b);
		ll l=1,r=b,p;
		while(l<=r)
		{
			ll mid=l+r>>1;
			if(check(mid))
				l=mid+1,p=mid;
			else
				r=mid-1;
		}
		ll res=a-1+p;	
		cout<<res<<'\n';
	}	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/noone0/article/details/79874399