1042.D Petya and Array 字首 + 樹狀陣列
阿新 • • 發佈:2018-11-20
11.19.2018
1042.D Petya and Array
New Point:
字首 + 樹狀陣列 :樹狀陣列逐個維護字首個數
Describe:
給你一個陣列,一個標記數,問你有多少區間[l,r]使得這個區間的和小於這個標記數值
Solution:
沒能想到
字首陣列 + 樹狀陣列快速查詢
記錄字首陣列sum[i],得到區間和為sum[i] - sum[j] < t,轉化為求sum[i] - t < sum[j],遍歷i,求取情況,然後利用樹狀陣列快速查詢符合的區間j的個數
樹狀陣列維護的是 sum[j],而且遍歷i[1,n]的時候j的範圍是
Code:
#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; }