可以发现在
k
个点间连边,剩下
那么答案就是
n−k+min(n−k,k(k−1)2)
注意到
n−k
是单调递减的,
k(k−1)2
是单调递增的。
所以存在
k0
,使在
[1,k0]
间
min(n−k,k(k−1)2)
是单调递增的,在
[k0+1,n]
间
min(n−k,k(k−1)2)
是单调递减的。
那么在
[1,k0]
答案是单调递增的,在
[k0+1,n]
答案是单调递减的。
用三分就可以求出答案。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
int i,j,k,n,m,p,Q;
double Ans,l,r,m1,m2;
inline double Min(double x,double y){
return x<y?x:y;
}
inline double Max(double x,double y){
return x<y?y:x;
}
inline double F(double x){
return n-x+Min(x*(x-1)/2,n-x);
}
int main(){
scanf("%d",&Q);
while(Q--){
scanf("%d",&n);
l=1;r=n;
while(r-l>0.1){
m1=(r-l)/3;m2=r-m1;m1+=l;
if(F(m1)>F(m2))r=m2;else l=m1;
}
l=(int)((l+r)/2);
printf("%.0lf\n",Max(F(l),F(l+1)));
}
return 0;
}