专栏文章
P14576 题解
P14576题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min237o2
- 此快照首次捕获于
- 2025/12/01 19:18 3 个月前
- 此快照最后确认于
- 2025/12/01 19:18 3 个月前
显然在每行后面都放一个光标一定不劣。接下来先考虑光标向左移动的情况,那么处在同一行的光标一定是若干个连续行末的光标,为了让它们同行的机会尽可能多,应该在它们前面最长的一行来实现。考虑枚举区间左端点,同时记录前缀最大值,那么显然可以直接二分最远的右端点,要求这两个光标距离不能超过前缀最大值,然后更新答案即可。时间复杂度 。
CPP#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
#define N 1000010
int n,a[N],sum[N],mx,ans;
void solve(){
ans=0;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i]+(i>1);
mx=0;//按左
for(int i=1;i<=n;i++){
mx=max(mx,a[i]);
int l=i,r=n,mid,pp=i;
while(l<=r){
mid=(l+r)/2;
if(sum[mid]-sum[i]<=mx)pp=mid,l=mid+1;
else r=mid-1;
}
ans=max(ans,pp-i+1);
}
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i]+(i<n);
mx=0;//按右
for(int i=n;i>=1;i--){
int l=1,r=i,mid,pp=i;
while(l<=r){
mid=(l+r)/2;
if(sum[i]-sum[mid]<=mx)pp=mid,r=mid-1;
else l=mid+1;
}
ans=max(ans,i-pp+1);
mx=max(mx,a[i]);
}
cout<<ans<<'\n';
return;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--)
solve();
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...