3 月2日 快慢指针之《挑选子串》

  1. 设置程序为同步关闭模式,这会使得 I/O 操作更加快速。

  2. 使用 cin 读取三个整数 nm 和 k:其中 n 表示数组的长度,m 是比较的阈值,而 k 指需要寻找至少有多少个元素大于或等于阈值 m 的子区间。

  3. 通过循环从标准输入中读取数组 a 的所有元素。

  4. 初始化答案变量 ans=0

  5. 使用双指针技术来处理所有可能的连续子区间。外层循环遍历所有起点位置 i 而内层循环则尝试将终点位置 j 右移以扩展当前考虑的子区间。

  6. 如果遇到符合条件(即当前子区间中大于或等于 m 的元素数量达到 k)时,计算出所有包括其及其右端可能延伸出去(直到 n)的有效子区间数量,并将这个数量累加到答案 ans 中。

  7. 最后输出计算出来的答案 ans。

  8. #include <iostream>
    const int N=1e6+9;
    int a[N];
    using namespace std;
    int main()
    {
      ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
      int n,m,k;cin>>n>>m>>k;
      for(int i=1;i<=n;i++)
      {
        cin>>a[i];
      }
      int ans=0;
      for(int i=1,j=0,cnt=0;i<=n;++i)
      {
        while(i>j||(j+1<=n&&cnt<k))cnt+=(a[++j]>=m);
        if(cnt>=k)ans+=n-j+1;
        cnt-=(a[i]>=m);
      }
      cout<<ans<<endl;
      return 0;
    }

具体代码分析:

// 初始化计数器 cnt 和结果 answer
int ans=0;
for(int i=1,j=0,cnt=0;i<=n;++i)
{   
    // 尝试扩展右指针 j 直到不能再扩展为止(即当下一个位置还未达到数组尾端且目前为止满足小于 k 条件)
    while(i>j||(j+1<=n&&cnt<k)) cnt+=(a[++j]>=m);
    
    // 当找到至少有 k 个元素符合条件时开始对答案进行统计
    if(cnt>=k) ans+=n-j+1; 
    
    // 左指针向右移动之前从计数器 cnt 中减去左端点存放数字是否满足条件
    cnt-=(a[i]>=m); 
}

举例说明执行过程:假设输入为 n=5, m=3, k=2,数组 a=[1, 3, 5, 2, 4]。

  • 对于 i=1: 扩展 j 直到 a[2] >= m 及 a[3] >= m,随后 cnt = 2,满足条件且 ans = (5 - 3 + 1) = 3。
  • 随着 i 向右移动: 每次检查并调整 j 将贡献更多符合条件子序列至 ans。
  • 程序最终输出总共有多少种符合题设上述限制条件的不同连续子列。
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值