003.二分
二分
Although the basic idea of binary search is comparatively straightforward, the details can be surprisingly tricky...
思路很简单,细节是魔鬼
二分查找
在给定有序数组中查找是否存在某元素
- 存在:返回下标
- 不存在:返回-1
int binarySearch(vector<int>&nums,int target){
int l=0,r=nums.size()-1,mid;
while(l<=r){
mid=(l+r)>>1;//位运算:二进制下右移一位,等价于mid=(l+r)/2
if(nums[mid]==target)return mid;
else if(nums[mid]>target)r=mid-1;
else l=mid+1;
}
return -1;
}
在给定数组(不一定有序)中查找是否存在某元素
- 存在:返回1
- 不存在:返回0
bool binarySearch(vector<int>&nums,int target){
sort(nums.begin(),nums.end());
int l=0,r=nums.size()-1,mid;
while(l<=r){
mid=(l+r)>>1;
if(nums[mid]==target)return 1;
else if(nums[mid]>target)r=mid-1;
else l=mid+1;
}
return 0;
}
//为了避免(l+r)造成的整型溢出
//优化:mid=l+(r-l)>>1
二分的应用依赖有序性
基于有序性,查找失败后可以缩小一半的查找范围,实现O(logn)查找
抽象有序性
给定一个bool数组[0,0,0,0,0,0,0,1,1,1,1,1,1]
要求返回第一个1的下标
题目保证存在至少一个1
int solve(vector<bool>&abstract){
int l=0,r=abstract.size()-1,mid,ans;
while(l<=r){
mid=l+(r-l)>>1;
if(abstract[mid])ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
同理我们可以找到最后一个0的下标
如果把bool数组反过来[1,1,1,1,1,1,0,0,0,0,0,0,0,0,0]也不在话下,只需更改判断逻辑就可以了
我们如果遇到这样的问题:
- 存在某种有序性(可能十分隐蔽)
- 求临界条件(一般是求满足条件的最大的最小值,最小的最大值)
一般都可以抽象出一个bool函数
模板如下
bool check(int x){
…………
}
void solve(){
//[min_ans,max_ans]:初始查找范围
int l=min_ans,r=max_ans,mid,ans;
while(l<=r){
mid=l+(r-l)/2;
if(check(mid))ans=mid,…………;
else …………;
}
printf("%d\n",ans);
}
根据题目逻辑实现check函数和范围修改
一道例题:序列划分
题目描述:
给定n个正整数a_1,a_2,……,a_n,将这个序列从左到右划分成m段,使得每段至少有一个数。
你需要让数字之和最大的那一段的数字和尽可能得小。
Input
第一行包含一个正整数T(1<=T<=10),表示测试数据的组数。
每组数据第一行包含两个正整数n,m(1<= m<= n<= 100000)。
第二行包含n个正整数a_1,a_2,……,a_n(1<= a_i<= 10^9)。
Output
对于每组数据输出一行一个整数,即你找到的方案中,数字之和最大的那一段的数字和。
Sample Input
1
6 4
1 5 4 6 2 3
Sample Output
6
思路:
-
发现单调性:
设答案为ans。随着ans减小,能分得的最大段数增多(不减少)
-
抽象bool函数:
段数小于等于m时合法(数字之和小于ans的一段分成的两段的数字之和仍然小于ans,这意味着当段数小于m时可以通过分裂操作将段数调整至m,这是合法的)
段数大于m时非法
-
确定初始范围:
ans不小于a[1,2,……,n]的最大值(m=n时)
ans不大于a[1,2,……,n]的总和(m=1时)
-
设计check函数:
简单贪心:
从左到右累加,一旦累加和大于ans就把当前元素当作下一个区间的第一个元素
O(n)算出ans情况下能分得的最大段数
-
二分答案:
套模板:
O(nlog(n))找到最小的ans
//观察数据范围,记得开long long
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=100005;
int n,m;
ll a[MAXN],min_ans,max_ans;
bool check(ll x){
ll cnt=1;
ll cur_sum=0;
for(int i=0;i<n;++i){
if(cur_sum+a[i]<=x){
cur_sum+=a[i];
}
else{
cur_sum=a[i];
cnt++;
}
}
return cnt<=m;
}
void solve(){
ll l=min_ans,r=max_ans,mid,ans=r;
while(l<=r){
mid=l+(r-l)/2;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans<<'\n';
}
int main(){
cin.tie(0)->sync_with_stdio(0);
int T;
cin>>T;
while(T--){
cin>>n>>m;
min_ans=-1;
max_ans=0;
for(int i=0;i<n;++i){
cin>>a[i];
max_ans+=a[i];
if(a[i]>min_ans)min_ans=a[i];
}
solve();
}
}
练习题
前5题涉及浮点数精度
code
//分蛋糕问题
//浮点数二分时需注意:
//循环终止条件为:r-l<1e-9(或者别的精度)
//缩小范围时使用l=mid或l=mid+1e-9,而不是l=mid+1(r同理)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=10005;
int n,k;
double M;
double a[MAXN];
bool check(double x){
int cnt=0;
for(int i=0;i<n;++i)cnt+=(int)(a[i]/x);
return cnt>=k;
}
void solve(){
double l=0,r=M,mid;
while(r-l>1e-5){
mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
printf("%.2lf\n",l);
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
//int T=read();
while(scanf("%d%d",&n,&k)){
if(n==0&&k==0)break;
M=0;
for(int i=0;i<n;++i){
scanf("%lf",a+i);
M+=a[i];
}
M/=k;
solve();
}
}
code
//与1551类似
//涉及圆周率:
//const double PI=acos(-1.0)或者const double PI=3.1415926(精度一般够用);
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=10005;
const double pi=acos(-1.0);
const double e=1e-5;
int n,f,R[MAXN],MR;
bool check(double x){
int cnt=0;
for(int i=0;i<n;++i){
cnt+=(int)(pi*R[i]*R[i]/x);
}
return cnt>f;
}
void solve(){
double l=0.0,r=pi*MR*MR;
while(r-l>e){
double mid=(l+r)/2.0;
if(check(mid))l=mid;
else r=mid;
}
printf("%.4lf\n",l);
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
int T=read();
while(T--){
n=read(),f=read();
MR=0;
for(int i=0;i<n;++i){
R[i]=read();
if(R[i]>MR)MR=R[i];
}
solve();
}
}
code
//函数在[0,100]明显单调
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=100005;
double Y;
inline double f(double x){
return 8*x*x*x*x+7*x*x*x+2*x*x+3*x+6;
}
void solve(){
if(f(0)>Y||f(100)<Y){
printf("No solution!\n");
return ;
}
double l=0.0,r=100.0,mid,ans;
while(r-l>1e-6){
mid=(l+r)/2.0;
if(Y-f(mid)<=1e-5)ans=mid,r=mid;
else l=mid;
}
printf("%.4lf\n",ans);
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
int T=read();
while(T--){
scanf("%lf",&Y);
solve();
}
}
code
//涉及简单物理知识
//cup应该是上粗下细的
//利用相似求出实际上表面半径
//台体体积=1/3*h*(S+s+sqrt(S*s))
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=100005;
const double pi=acos(-1.0);
double r,R,H,V;
void solve(){
double left=0,right=H,mid;
while(right-left>1e-9){
mid=(left+right)/2;
double r1=(R-r)*mid/H+r;
double v=pi/3*mid*(r*r+r1*r1+r*r1);
if(fabs(v-V)<=1e-9)break ;
else if(v>V)right=mid-1e-9;
else left=mid+1e-9;
}
printf("%.6lf\n",mid);
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
int T=read();
while(T--){
scanf("%lf %lf %lf %lf",&r,&R,&H,&V);
solve();
}
}
code
//中学物理题
//设角度为t,运动时间为T
//分解初速度:水平v*cos(t),竖直v*sin(t)
//分解运动:
//水平匀速直线:x=v*cos(t)*T
//竖直匀减速:y=v*sin(t)*T-g/2*T*T
//消去T
//y=x*tan(t)-(g*x*x)/(2*v*v*cos(t)*cos(t))
//现在已知y,x
//二分试出t即可
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=100005;
const double pi=acos(-1.0);
const double e=1e-9;
const double g=9.80;
double x,y,v;
void solve(){
double tant=v*v/(g*x);
double M=atan(tant);
double cost=cos(M);
double Ymax=x*tant-g*x*x/(2.0*v*v*cost*cost);
if(Ymax<y){
printf("-1\n");
return ;
}
double l=0,r=M,mid;
while(r-l>e){
mid=(l+r)/2;
double tanm=tan(mid);
double cosm=cos(mid);
double Ym=x*tanm-g*x*x/(2.0*v*v*cosm*cosm);
if(Ym>=y)r=mid;
else l=mid;
}
printf("%.6lf\n",l);
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
int T=read();
while(T--){
scanf("%lf%lf%lf",&x,&y,&v);
solve();
}
}
code
//直接暴力是O(n^3)
//类似哈希优化,不过我们手动二分查找
//实现O(n^2+nlog(n*n))
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=505;
int L,N,M,S;
int A[MAXN],B[MAXN],C[MAXN],x;
int AB[MAXN*MAXN];
bool check(int x){
int l=0,r=L*N-1;
while(l<=r){
int mid=(l+r)>>1;
if(AB[mid]==x)return 1;
else if(AB[mid]<x)l=mid+1;
else r=mid-1;
}
return 0;
}
void solve(){
for(int i=0;i<M;i++){
int tar=x-C[i];
if(check(tar)){
printf("YES\n");
return ;
}
}
printf("NO\n");
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
//int T=read();
int tot=0;
while(scanf("%d %d %d",&L,&N,&M)==3){
printf("Case %d:\n",++tot);
for(int i=0;i<L;i++)A[i]=read();
for(int i=0;i<N;i++)B[i]=read();
for(int i=0;i<M;i++)C[i]=read();
int p=0;
for(int i=0;i<L;i++){
for(int j=0;j<N;j++){
AB[p++]=A[i]+B[j];
}
}
sort(AB,AB+L*N);
S=read();
while(S--){
x=read();
solve();
}
}
}
code
//手动添加3块石头
//d[0]:初始位置
//d[n+1]:终点
//d[n+2]:无穷远
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x7fffffff
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=500005;
int L,n,m;
int d[MAXN];
int f(int x){
int cnt=0;
int i=0,j=0;
while(i<n+1){
while(j<=n+1&&d[j+1]-d[i]<=x)j++;
cnt++;
i=j;
}
return cnt;
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
//int T=read();
while(scanf("%d%d%d",&L,&n,&m)==3){
for(int i=1;i<=n;i++)scanf("%d",d+i);
sort(d+1,d+n+1);
d[0]=0;
d[n+1]=L;
d[n+2]=INF;
int max_d=0;
for(int i=1;i<=n+1;i++){
if(d[i]-d[i-1]>max_d)max_d=d[i]-d[i-1];
}
int l=max_d,r=L;
int ans=r;
while(l<=r){
int mid=l+(r-l)/2;
if(f(mid)<=m)ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
}
}
code
//与分蛋糕类而不同
//区别在于这里我们需要向上取整
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=500005;
int n,b,a[MAXN],M;
bool check(int x){
int cnt=0;
for(int i=0;i<n;++i){
cnt+=a[i]/x;
if(a[i]%x!=0)cnt++;
}
return cnt<=b;
}
void solve(){
int l=1,r=M,mid,ans=l;
while(l<=r){
mid=(l+r)>>1;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
//int T=read();
while(scanf("%d%d",&n,&b)==2&&n!=-1){
M=0;
for(int i=0;i<n;i++){
a[i]=read();
if(M<a[i])M=a[i];
}
solve();
}
}
code
//n<=1e12
//因为k>=2,所以r最多不超过40
//枚举r,二分查找合法的k
//注意:中心可以插1个或0个蜡烛
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=100005;
ll n;
void solve(){
ll r=1,k=n-1;
for(int i=2;i<=40;i++){
ll kl=2,kr=n;
while(kr>=kl){
ll km=kl+(kr-kl)/2;
ll sum=0;
ll t=1;
for(int j=1;j<=i;j++)
{
if(sum>n)break;
if(n/t<km){sum=n+1;break;}
t*=km;
sum+=t;
}
if(sum==n||sum==n-1){
if((km*i<r*k)||(km*i==r*k&&i<r))k=km,r=i;
break;
}
if(sum>n)kr=km-1;
else kl=km+1;
}
}
printf("%lld %lld\n",r,k);
}
signed main(){
while(scanf("%lld",&n)!=EOF){
solve();
}
}
code
//贪心:左边的元素越小越有利
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=100005;
int n,A[MAXN],B[MAXN];
bool check(int x){
for(int i=1;i<=n;i++)B[i]=A[i];
B[0]=-x;
for(int i=1;i<=n;i++){
if(B[i]>B[i-1]){
if(B[i]-B[i-1]-1<=x)B[i]=B[i-1]+1;
else B[i]-=x;
}
else{
if(B[i-1]+1-B[i]<=x)B[i]=B[i-1]+1;
else return 0;
}
}
return 1;
}
void solve(){
int l=0,r=1e6;
int ans=r;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
int T=read();
int tot=0;
while(T--){
printf("Case #%d:\n",++tot);
n=read();
for(int i=1;i<=n;++i)A[i]=read();
solve();
}
}
code
//每次合并操作相当于减少了k-1个元素,最后仅剩1个元素
//让较小的元素合并尽可能多次
//为方便操作,我们添加若干0元素,使得恰好每次合并k个元素,最后剩余一个,同时不影响cost
//最开始我是使用一个priority_queue(二叉堆),但push,pop都是O(logn)的
//而我们提前排序后从左往右合并天然满足递增
//可以再开一个数组存放合并后的新值
//每次合并时保证合并的是目前最小元素即可
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=100005;
int n,t,a[MAXN];
bool check(int x){
ll cost=0;
queue<ll>q1,q2;
int zeros=x-1-(n-1)%(x-1);
for(int i=0;i<zeros;i++)q1.push(0);
for(int i=0;i<n;i++)q1.push(a[i]);
while(q1.size()+q2.size()>1){
ll sum=0;
for(int i=0;i<x;i++){
if(!q1.empty()&&!q2.empty()){
if(q1.front()<q2.front())sum+=q1.front(),q1.pop();
else sum+=q2.front(),q2.pop();
}
else if(!q2.empty())sum+=q2.front(),q2.pop();
else if(!q1.empty())sum+=q1.front(),q1.pop();
else break;
}
cost+=sum;
q2.push(sum);
}
return cost<=t;
}
void solve(){
int l=2,r=n,mid,ans=r;
while(l<=r){
mid=(l+r)>>1;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
int T=read();
while(T--){
n=read(),t=read();
for(int i=0;i<n;++i)a[i]=read();
sort(a,a+n);
solve();
}
}
code
//通过copy一个有序数组A,实现尺取
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=100005;
int n,k,m;
int a[MAXN],A[MAXN];
bool check(int x){
int sum=0,cnt=0;
int r=0;
for(int l=0;l<n;++l){
while(r<n&&cnt<k){
if(a[r]>=x)cnt++;
r++;
}
if(cnt>=k)sum+=n-r+1;
if(sum>=m)return 1;
if(a[l]>=x)cnt--;
}
return sum>=m;
}
void solve(){
int l=0,r=n-1,mid,ans=l;
while(l<=r){
mid=(l+r)>>1;
if(check(A[mid]))ans=A[mid],l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
}
signed main(){
int T=read();
while(T--){
n=read(),k=read(),m=read();
for(int i=0;i<n;++i)a[i]=read(),A[i]=a[i];
sort(A,A+n);
solve();
}
}
code
//预处理出log2向上取整的值
//技巧:比较n^a(⌈log2n⌉)^b与k,为避免乘法溢出
//我们用k除以a个n,b个log2n,判断结果与1的关系
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=100005;
int a,b;
ll k;
ll s[100]={1};
bool check(ll x){
ll j;
for(j=0;j<=62;j++)if(x<=s[j])break;
long double t=k;
for(int i=0;i<a;i++){
t/=(long double)x;
if(t<1.0)return 0;
}
for(int i=0;i<b;i++){
t/=(long double)j;
if(t<1.0)return 0;
}
return 1;
}
void solve(){
ll l=0,r=k,mid,ans=l;
while(l<=r){
mid=(l+r)>>1;
if(check(mid))ans=mid,l=mid+1;
else r=mid-1;
}
printf("%lld\n",ans);
}
signed main(){
//cin.tie(0)->sync_with_stdio(0);
int T=read();
for(int i=1;i<=62;i++)s[i]=(ll)(1ll<<i);
while(T--){
a=read(),b=read();
scanf("%lld",&k);
solve();
}
}
code
//最大的最小值
//每次操作a-2,b+1,总和-1
//注意:我们可以实现对一个元素的-1操作(先-2,再+1)
//二分最小值,check能否合法地变成稳定数组
//check的标准:使所有元素不小于min,也就是将所有比mid小的元素x变成不小于min的数,所需的最小up(+1)次数为(min-x)
//我们统计一共最少需要多少次up操作,最多可以实现多少次down(-2)操作
//满足:如果down<up,说明无法合法达到稳定
//down==up,正好
//down>up,我们只需up次down操作,剩下的down不进行,不影响数组的稳定性
//注意:我们对一个元素-1(-2+1)进行了一次down,一次up,不影响最后down与up的比较,与就是说我们无需考虑恰好比min大1的元素
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=300005;
int n;
ll x[MAXN],M,m;
bool check(ll mid){
ll down=0,up=0;
for(int i=0;i<n;i++){
if(mid>x[i])up+=mid-x[i];
else if(x[i]>mid+1) down+=(x[i]-mid)/2;
}
return down>=up;
}
void solve(){
ll l=m,r=M,mid,ans;
while(r>=l){
mid=(l+r)>>1;
if(check(mid))ans=mid,l=mid+1;
else r=mid-1;
}
printf("%lld\n",ans);
}
signed main(){
int T=read();
while(T--){
n=read();
M=0;
m=1e8;
for(int i=0;i<n;++i){
scanf("%lld",x+i);
if(x[i]>M)M=x[i];
if(x[i]<m)m=x[i];
}
solve();
}
}
code
//例题
// class Solution {
// public:
// int splitArray(vector<int>& nums, int k) {
// int n=nums.size();
// int sum=0,max=0;
// for(int w:nums){
// sum+=w;
// if(w>max)max=w;
// }
// int l=max,r=sum;
// int ans=r;
// while(l<=r){
// int mid=(l+r)>>1;
// if(f(mid,nums)<=k)ans=mid,r=mid-1;
// else l=mid+1;
// }
// return ans;
// }
// int f(int x,vector<int>&nums){
// int cnt=1;
// int sum=0;
// for(int w:nums){
// if(sum+w<=x){
// sum+=w;
// }
// else{
// cnt++;
// sum=w;
// }
// }
// return cnt;
// }
// };
code
//二分+滑动窗口
// class Solution {
// int n;
// public:
// int smallestDistancePair(vector<int>& nums, int k) {
// n=nums.size();
// sort(nums.begin(),nums.end());
// int l=0,r=nums[n-1]-nums[0],mid,ans;
// while(l<=r){
// mid=(l+r)>>1;
// if(check(mid,nums,k))ans=mid,r=mid-1;
// else l=mid+1;
// }
// return ans;
// }
// bool check(int x,vector<int>&nums,int k){
// int cnt=0;
// int i=0,j=0;
// for(;i<n;i++){
// while(j+1<n&&nums[j+1]-nums[i]<=x)j++;
// cnt+=(j-i);
// }
// return cnt>=k;
// }
// };
code
// class Solution {
// public:
// int minEatingSpeed(vector<int>& piles, int h) {
// int n=piles.size();
// int l=1,r=1e9+1;
// int ans=l;
// while(l<=r){
// int mid=(l+r)>>1;
// int cnt=0;
// for(int ba:piles){
// cnt+=ba/mid;
// if(ba%mid)cnt++;
// if(cnt>h)break;
// }
// if(cnt<=h)ans=mid,r=mid-1;
// else l=mid+1;
// }
// return ans;
// }
// };
code
// class Solution {
// public:
// int f(int x,vector<int>&wight){
// int cnt=1;
// int N=x;
// for(int w:wight){
// if(N>=w){
// N-=w;
// }
// else{
// cnt++;
// N=x-w;
// }
// }
// return cnt;
// }
// int shipWithinDays(vector<int>& weights, int days) {
// int n=weights.size();
// int sum=0,max=0;
// for(int w:weights){
// sum+=w;
// if(w>max)max=w;
// }
// int l=max,r=sum;
// int ans=r;
// while(l<=r){
// int mid=(l+r)>>1;
// if(f(mid,weights)<=days)ans=mid,r=mid-1;
// else l=mid+1;
// }
// return ans;
// }
// };
code
//记得开long long
// class Solution {
// public:
// long long maxRunTime(int n, vector<int>& batteries) {
// long long sum=0;
// int m=1e9;
// for(int t:batteries){
// if(t<m)m=t;
// sum+=(long long)t;
// }
// long long l=(long long)m,r=sum,mid,ans;
// while(l<=r){
// mid=(l+r)>>1;
// if(check(mid,n,batteries))ans=mid,l=mid+1;
// else r=mid-1;
// }
// return ans;
// }
// bool check(long long x,int n,vector<int>&batteries){
// long long sum=0;
// for(int t:batteries){
// if((long long)t>=x)sum+=x;
// else sum+=(long long)t;
// }
// return sum>=n*x;
// }
// };
code
// class Solution {
// public:
// long long minimumTime(vector<int>& time, int totalTrips) {
// if(time.size()==1)return (long long)time[0]*totalTrips;
// int m=1e7;
// for(int t:time)if(t<m)m=t;
// long long l=(long long)m,r=(long long)m*(long long)totalTrips,mid,ans;
// while(l<=r){
// mid=(l+r)>>1;
// if(check(mid,time,totalTrips))ans=mid,r=mid-1;
// else l=mid+1;
// }
// return ans;
// }
// bool check(long long x,vector<int>&time,int k){
// long long cnt=0;
// for(int t:time){
// cnt+=x/t;
// if(cnt>=k)return 1;
// }
// return cnt>=k;
// }
// };
//一眼丁真鉴定为忘开long long

浙公网安备 33010602011771号