题意:两个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;
}