11.19.2018ios
前缀 + 树状数组 :树状数组逐个维护前缀个数数组
Describe:spa
给你一个数组,一个标记数,问你有多少区间[l,r]使得这个区间的和小于这个标记数值blog
没能想到string
前缀数组 + 树状数组快速查询it
记录前缀数组sum[i],获得区间和为sum[i] - sum[j] < t,转化为求sum[i] - t < sum[j],遍历i,求取状况,而后利用树状数组快速查询符合的区间j的个数io
树状数组维护的是 sum[j],并且遍历i[1,n]的时候j的范围是[0,i-1],因此对于一个新i,咱们应该找到sum[i-1]在树上的位置进行全局更新,可是对于第一个i,更新sum[0] = 0便可,能够想到j取0的时候表示a1 + …… + aiclass
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 2e5 + 1e3; ll sum[maxn]; ll f[maxn]; ll tree[maxn]; int n; ll lowbit(ll x) { return x & (-x); } void add(ll x) { while(x <= n+1) { ++tree[x]; x += lowbit(x); } } ll Get(ll x) { ll ans = 0; while(x > 0) { ans += tree[x]; x -=lowbit(x); } return ans; } int main() { ll t; while(~scanf("%d %lld",&n,&t)) { memset(sum,0,sizeof(sum)); memset(tree,0,sizeof(tree)); for(int i = 1;i <= n;++i) { scanf("%lld",&sum[i]); sum[i] += sum[i-1]; f[i] = sum[i]; } f[0] = 0; sort(f,f+n+1); ll ans = 0; for(int i = 1;i <= n;++i) { add(lower_bound(f,f+n+1,sum[i-1]) + 1 - f); ans += i - Get(lower_bound(f,f+n+1,sum[i] - t + 1) - f); } printf("%lld\n",ans); } return 0; }