挑选字串(Lanqiao OJ 1621)

#双指针 #快慢指针


题目描述

有n个数,和一个整数m。

现要从这n个数中选出一个连续子串,要求这个子串里面至少有k个数要大于等于m。

问一共能选出多少个子串(显然子串长度要大于等于k)。


输入描述

输入第一行是3个整数n、m、k。

输入第二行是n个整数,a1,a2,...,an,表示序列。


输出描述

输出一个整数表示答案。


样例输入

7 4 2
4 2 7 7 6 5 1

样例输出

18

题解:

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 9;
int a[N];

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;
}

总结:

首先开一个数组存储这n个数。遍历数组进行赋值。

使用双指针i,j表示区间,通过for循环对双指针区间进行移动。

①当i > j ,即左指针的值大于右指针的值,显然这个区间不合法。或者右指针有向右移动的空间并且不满足条件k时,即(j + 1 <= n && cnt < k)。此时++j,使右指针向右移动,并且判断该值是否大于m,若满足条件就返回true,强制转换为1,使cnt+1。使    cnt += (a[++j] >= m);

②在执行①的过程中,当出现cnt的个数大于k,即满足题目要求时,此时答案子串的个数为末尾数组的值减去当前右指针的值,即ans += n - j + 1。(也就是:当前右指针为满足条件的最小区间,右边的都比它大,也就都满足条件。)        相应地,在右指针向右移的过程中,左指针也在向右移,若左指针所走过的值>m即满足条件,则令cnt -= (a[i] >= m);(也就是:减去之前包含在区间内满足条件的点,而现在不在了。)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值