题解:
考察点: 滑动窗口,数形结合
易错点:
在本题中数据范围为,如果使用暴力求解是行不通的,因为如果使用复杂度为
的暴力,那运算次数将达到
,一般来说,在
时间范围内
所能抗住的运算次数在
解法:滑动窗口
首先,先从下图来观察出一个很重要的结论:
对于一个全由正整数构成的序列来说,如果区间中所有元素的和大于等于
,则区间
中所有元素的和一定大于等于
。这是一个非常显然的结论,但在这里却非常有用。假设位置
为区间
和
的分隔线,
中所有元素的和大于等于
,则当前位置
对答案的贡献为
,因为后面无论加上多少个元素,总可以,满足区间的和大于等于
。
有了上述结论,可以很自然使用滑动窗口算法来做这个问题。对于当前位置,指针
指向其所对应区间
的开头。如果
大于
,则指针
从
的开始位置往后移动,直到
所对应的区间小于
为止。同时指针每移动一次,
对答案的贡献增加
,因为其后的都满足大于等于
。整个过程中最多
遍历1次,
遍历一次,所以复杂度为
,也就是
级别的复杂度
#include "bits/stdc++.h" using namespace std; const int maxn=1e6+100; typedef long long LL; int n,a[maxn]; LL x; int main() { scanf("%d%lld",&n,&x); LL sum=0,ans=0; int j=1; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sum+=a[i]; if(sum>=x){ ans+=n-i+1; while(j<=i&&sum>=x){ sum-=a[j]; j++; if(sum>=x) ans+=n-i+1; else break; } } } printf("%lld\n",ans); return 0; }