首先,容易证明满足条件的$ip_{i}$必然是一个前缀
将其看成一张二分图,$i$向满足$ip_{i}<xy$的$p_{i}$连边,即找到一个前缀满足其有完美匹配
二分枚举前缀长度$k$,根据hall定理,即要求$\forall S\in [1,k],\lfloor\frac{xy-1}{\min_{i\in S}i}\rfloor\ge |S|$,很明显$S$是一个后缀时最难满足,换言之即要求$\forall 1\le i\le k,\lfloor\frac{xy-1}{i}\rfloor\ge k-i+1$($S=[i,k]$)
这又等价于$xy>ik-i^{2}+i$,后者是一个关于$i$的二次函数,求最大值即可判定
还有一个特殊的问题,左边的$x$和右边的$y$都不能被选入答案,换言之,即当$i\le x$,右式应为$k-i$;当$\lfloor\frac{xy-1}{\min_{i\in S}i}\rfloor\ge y$,左式(即该式)应为$\lfloor\frac{xy-1}{\min_{i\in S}i}\rfloor-1$
同时对于第二种情况,可以对$|S|$分类讨论,若$|S|<y$则减1无影响,若$|S|\ge y$则必然要减1(若该值小于$y$减1同样无影响),减1也可以看作对$|S|$加1,即$|S|\ge y$时可以加1
更具体的,对$i$作以下分类讨论:
1.对于$1\le i\le \min(x-1,k-y+1)$,求出$-i^{2}+(k+1)i$的最大值;
2.若$x\le k-y+1$,则对于$x<i\le k-y+1$,求出$-i^{2}+(k+2)i$的最大值;若$k-y+1<x$,则对于$k-y+1<i\le \min(x-1,k)$,求出$-i^{2}+ki$的最大值;
3.若$\max(x,k-y+1)<i\le k$,求出$-i^{2}+(k+1)i$的最大值
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 int t; 5 ll x,y; 6 ll get_mx(ll b,ll l,ll r){ 7 if (l>r)return 0; 8 if (b%2==0){ 9 if ((l<=b/2)&&(b/2<=r))return b*b/4; 10 return max((b-l)*l,(b-r)*r); 11 } 12 if ((l<=b/2)&&(b/2<=r)||(l<=b/2+1)&&(b/2+1<=r))return (b/2)*(b/2+1); 13 return max((b-l)*l,(b-r)*r); 14 } 15 bool pd(ll k){ 16 if (get_mx(k+1,1,min(x-1,k-y+1))>=x*y)return 0; 17 if (get_mx(k+2,x+1,k-y+1)>=x*y)return 0; 18 if (get_mx(k,k-y+2,min(x-1,k))>=x*y)return 0; 19 if (get_mx(k+1,max(x,k-y+1)+1,k)>=x*y)return 0; 20 return 1; 21 } 22 int main(){ 23 scanf("%d",&t); 24 while (t--){ 25 scanf("%lld%lld",&x,&y); 26 if (x>y)swap(x,y); 27 ll l=0,r=2e9; 28 while (l<r){ 29 ll mid=(l+r+1>>1); 30 if (pd(mid))l=mid; 31 else r=mid-1; 32 } 33 printf("%lld\n",l-(l>=x)); 34 } 35 }
原文:https://www.cnblogs.com/PYWBKTDA/p/14057276.html