题目链接:

https://atcoder.jp/contests/abc130/tasks/abc130_d

题意:给你一个长度为N 的数组 , 和一个K。问该数组的连续子序列和大于等于k的个数。

俩种方法

  1. 尺取法

从该数组的第一位开始往后加一直到sum > k结束,记录此时位置pos,ans += n-pos+1;.

也就是说 pos后的所有数到第一位都是大于等于k , 满足条件。

然后 , 再从该数组的第二位在上次的基础上继续往后加 , 直到满足条件

2.前缀和加二分

取该数组的前缀和 , 二分找第一个大于等于a[i]+k的数 , 同上ans += n-pos+1;.

代码:

尺取法:(记得加long long)

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5+8;
int main()
{
	ll n , m , a[maxn];
	ll sum = 0 , ans = 0;
	scanf("%lld %lld" , &n , &m);
	for(int i = 1 ; i <= n ; i++)
	{
		scanf("%lld" , &a[i]);
	}
	int t = 0 , s = 1;
	while(1)
	{
		while(sum < m && t <= n)
		{
			sum += a[++t];
		}
		if(sum < m) break;
		ans += (n-t+1);
		sum -= a[s];
		s++;
	}
	printf("%lld\n" , ans);
	return 0;
}

前缀和+二分:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+8;
int main()
{
	int n , k , x , a[maxn];
	scanf("%d %d" , &n , &k);
	a[0] = 0;
	for(int i = 1 ; i <= n ; i++)
	{
		scanf("%d" , &x);
		a[i] = a[i-1] + x;
	}
	int ans = 0;
	for(int i = 1 ; i <= n ; i++)
	{
		int pos = lower_bound(a+i , a+n+1 , a[i-1]+k)-a;
		if(pos == n+1 &&a[n] < a[i-1] + k) break;
		ans += (n-pos+1);
	}
	printf("%d\n" , ans);
	return 0;
}