把原数组转为前缀和:pre[0]=0,pre[i]=papers[0..i-1]之和。任意连续子段 [l..r] 的和为:
sum = pre[r+1] - pre[l]。
要求 left <= sum <= right,等价于对每个 j = r+1,统计之前的 i < j 中有多少个 pre[i] 落在区间:
pre[i] ∈ [ pre[j]-right , pre[j]-left ]。
所以问题变成:按顺序枚举 pre[j],动态维护已出现的前缀和值集合,支持“统计某个数值区间内的出现次数”。
今天,小明的数学老师带来了一叠数字卡牌,每张卡牌上标有数字,有正有负也有零。老师打乱了卡牌顺序,并将牌面展示出来。接着老师在黑板上写下了一个闭区间范围 [left, right]。
老师对小明说:“你可以从这叠卡牌中任意抽取一叠,起始位置不限,抽取的张数不限,但是有个要求,你抽取出的卡牌,牌面加起来的和需要落在黑板上的区间范围内。小明,你算算看,一共能有几种抽取方法?”
小明听完,眼冒金星。你能帮助小明写个程序,算出有几种方法吗?
n(1 < n <= 10000)papers[](-255 <= papers[i] <= 255),共 n 个整数left 与右值 right(-2550000 <= left <= right <= 2550000)输入:
4
1 -1 1 -1
0 0
输出:
4
解释:
共有4张纸牌,牌面数字为1,-1,1,-1,方法为取第1张到2张,取第2张到第3张,取第3张到4张,取第1到4张,共4种
输入:
3
-3 4 -2
-3 2
输出:
5