题目链接:
https://atcoder.jp/contests/abc130/tasks/abc130_d
题意:给你一个长度为N 的数组 , 和一个K。问该数组的连续子序列和大于等于k的个数。
俩种方法
- 尺取法
从该数组的第一位开始往后加一直到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;
}