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; }