Codeforces Round #510 (Div. 2) D. Petya and Array(離散化+反向樹狀陣列)
阿新 • • 發佈:2018-11-22
http://codeforces.com/contest/1042/problem/D
題意
給一個數組n個元素,求有多少個連續的子序列的和<t
(1<=n<=200000,abs(a[i])<=1e9)
思路
- 將公式轉化以下,sum[r]-sum[l-1]<t 變成 sum[r]<sum[l-1]+t
- 可以考慮遍歷每個r,先更新sum[r-1]+t,統計有多少滿足條件的sum[l-1],反向樹狀陣列維護即可
實現細節
- 對於每個r是更新他的sum[r-1]
- 因為要統計>sum[r]的數有多少,但是反向樹狀陣列是包含自己當前這個點的,所以要加一
- 反向樹狀陣列的右邊界最好是陣列大小
#include<bits/stdc++.h> #define M 400005 #define ll long long using namespace std; int tr[M]; int n,tot,i; ll tp,p[M],x[M],ans,t; int lowbit(int x){return x&(-x);} void add(int x){ while(x>0){ tr[x]++;x-=lowbit(x); } } int qy(int x){ x++; // int ans=0; while(x<M){ // ans+=tr[x];x+=lowbit(x); } return ans; } int fd(ll x){ return lower_bound(p,p+tot,x)-p+1; } int main(){ cin>>n>>t; tot=0; for(i=1;i<=n;i++){ scanf("%lld",&x[i]); x[i]+=x[i-1]; p[tot++]=x[i]; p[tot++]=x[i]+t; } sort(p,p+tot); tot=unique(p,p+tot)-p; ans=0; for(i=1;i<=n;i++){ add(fd(x[i-1]+t)); // ans+=qy(fd(x[i])); //cout<<ans<<endl; } cout<<ans; }