[CodeForces]1042D

大意:求一个序列有几个子序列的和小于给定值,里面的数有正有负,序列长度≤200000。

列个式子,其实求的是sum[r]-sum[l-1]<T

sum[r]-T<sum[l-1]

所以我们可以枚举r,然后用树状数组找小于sum[r]-T的数的个数。记得要在树状数组里先加一个0,表示L取1,即从头开始。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=100005;
long long n,pre[N],a[N],ans,t[N],T,sum,tp[N];
void add(long long i) {for(;i<N;i+=i&-i) t[i]++;}
long long ask(long long i) {long long res=0;for(;i;i-=i&-i) res+=t[i];return res;}
int main() {
    scanf("%lld%lld",&n,&T);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]),pre[i]=pre[i-1]+a[i],tp[i]=pre[i];
    sort(tp+1,tp+2+n);
    int u=unique(tp+1,tp+2+n)-tp-1;
    for(int i=0;i<=n;i++) pre[i]=lower_bound(tp+1,tp+1+u,pre[i])-tp;
    add(pre[0]);
    for(int i=1;i<=n;i++) {
        int pos=lower_bound(tp+1,tp+1+u,tp[pre[i]]-T)-tp;
        if(tp[pos]!=tp[pre[i]]-T) pos--;    
        ans+=i-ask(pos);
        add(pre[i]);
    }
    cout<<ans<<endl;
    return 0;
}
Petya and Array
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9669615.html