首先想到双指针扫描,但双指针最差2×N复杂度,而答案最大可以是N^2,直接求和扫描得到的结果一定会漏掉。
由于都是正整数,所以,对于刚扫到的某个区间[a, b],如果是合法的,那么就是以b为结尾合法区间中和
最大的一个区间,则以a+1~b为区间左端点的区间都是合法的,所以,对于扫到的合法区间要累加 b - a + 1。
#include<bits/stdc++.h>
const int N = 1e5 + 10;
typedef long long ll;
using namespace std;
int num[N];
void run()
{
int n, p;
ll ans = 0;
int sum = 0;
scanf("%d%d", &n, &p);
for (int i = 0; i < n; i++)
scanf("%d", num + i);
int l = 0;
for (int i = 0; i < n; i++)
{
sum += num[i];
if (sum <= p)//当前位置加了后,统计以i为区间右端点的合法区间数
ans += i - l + 1;
else
{
while (l <= i && sum > p)//l要直到i,因为可能本身就是大于p的。
{
sum -= num[l];
l++;
}
//如果l>i这里会加0,不影响答案,如果l<=i则sum<p成立,
//统计i为右端点的合法区间数
ans += i - l + 1;
}
}
printf("%lld\n", ans);
}
int main()
{
int T, cas = 1;
scanf("%d", &T);
while (T--)
{
printf("Case #%d: ", cas++);
run();
}
return 0;
}