1042.D Petya and Array 前綴 + 樹狀數組
阿新 • • 發佈:2018-11-20
clas tree 快速 tdi ons str while har 快速查詢 1042.D Petya and Array
,我們應該找到sum[i-1]在樹上的位置進行全局更新,但是對於第一個i,更新sum[0] = 0即可,可以想到j取0的時候表示a1 + …… + ai
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的範圍是[0,i-1],所以對於一個新i
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; }
1042.D Petya and Array 前綴 + 樹狀數組