F. ATM and Students (双指针 / 二分+rmq)

博客探讨了如何找到序列中最长子段,其所有前缀和均大于等于给定常数s。首先介绍了双指针策略,解释了为何移动左指针l不会损失最优解。接着,讨论了使用二分搜索结合RMQ(Range Minimum Query)来检查特定长度子段是否满足条件,并提到了使用ST表或线段树实现RMQ的可能性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

给定序列,求出最长的子段,满足其每个前缀和+s都大于等于0,s是给定的常数。

双指针:

对于每个l,求出其满足条件的最远的r,用于更新答案,
此时sum+a[r+1] +s < 0.
我们再把l右移一格,继续求最远的r。这样是不会损失最优解的,原因如下:
l移动前,如果a[l]小于等于0,那么r接下来继续右移并更新答案即可;
如果a[l]大于0,移动后一定有[l+1,r+1]+s<0,所以r不会右移,l会继续右移,而这个l贡献的答案一定小于移动前贡献的答案,所以不会损失最优解。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 2e5+7;
int n,s;
int a[maxn];
//给定序列 求最长的子段满足 每个前缀和都大于等于给定的s*-1
//双指针
//对于l 求出最远的满足条件的r 更新答案 此时ret+a[r+1]-s < 0
//l右移一位 此时是满足双指针单调性的:
//如果a[l]小于等于0 那么r接下来继续右移即可 
//如果a[l]大于0 由于[l+1,r+1]必定小于0 r会继续右移 为什么不考虑[l+1,r]的答案呢?因为一定小于r-l+1
int main()
{
   
    int t;cin>>t;
    while(t--)
    {
   
        scanf("%d %d",&n,&s);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        int al=0,ar=-1,l=1,r=1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值