-
设置程序为同步关闭模式,这会使得 I/O 操作更加快速。
-
使用
cin
读取三个整数n
、m
和k
:其中n
表示数组的长度,m
是比较的阈值,而k
指需要寻找至少有多少个元素大于或等于阈值m
的子区间。 -
通过循环从标准输入中读取数组
a
的所有元素。 -
初始化答案变量
ans=0
。 -
使用双指针技术来处理所有可能的连续子区间。外层循环遍历所有起点位置 i 而内层循环则尝试将终点位置 j 右移以扩展当前考虑的子区间。
-
如果遇到符合条件(即当前子区间中大于或等于 m 的元素数量达到 k)时,计算出所有包括其及其右端可能延伸出去(直到 n)的有效子区间数量,并将这个数量累加到答案 ans 中。
-
最后输出计算出来的答案 ans。
-
#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。
- 程序最终输出总共有多少种符合题设上述限制条件的不同连续子列。