飛步A輪筆試題3 子陣列的和
題目3 : 子陣列的和
時間限制:10000ms
單點時限:1000ms
記憶體限制:256MB
描述
給定一個包含N個整數的陣列A = [A1, A2, ... AN],請你計算有多少個子陣列B = [Ai, Ai+1, ... Aj] (i ≤ j) 滿足B中所有整數的和小於K。
輸入
第一行包含兩個整數N和K。
第二行包含N個整數A1, A2, ... AN。
對於30%的資料,1 ≤ N ≤ 1000
對於另外30%的資料,0 < Ai ≤ 100000
對於100%的資料,1 ≤ N ≤ 100000 -100000 ≤ Ai ≤ 100000
輸出
一個整數,代表答案。
樣例輸入
4 -1 -2 1 -2 3
樣例輸出
3
// 後來才知道是樹狀陣列的模版題
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<vector>
typedef long long ll;
const int maxn = 100000;
const int inf = 1e9;
using namespace std;
int n,a[maxn+5];
ll sum[maxn+5], p[maxn+5],K;
int C[maxn+5],num[maxn+5];
int lowbit(int x) {return x&-x;}
int Sum(int x)
{
int ret = 0;
while(x>0)
{
ret+=C[x];
x-=lowbit(x);
}
return ret;
}
void add(int x,int d)
{
while(x<=n+1)
{
C[x]+=d;
x+=lowbit(x);
}
}
int index(ll x)
{
int l = 0, r = n+1, mid;
while(r-l>1)
{
mid = (l+r)>>1;
if(p[mid]<=x) l = mid;
else r = mid;
}
return l;
}
int main()
{
scanf("%d %lld",&n,&K);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i] = sum[i-1] + a[i];
p[i] = sum[i];
}
p[n+1] = 0;
sort(p+1,p+n+2);
ll ans = 0;
add(index(sum[0]),1);
for(int i=1;i<=n;i++)
{
ll w = sum[i] - K;// sum[i] - sum[j] < K, sum[j] > sum[i] - K
ans+=i - Sum(index(w));
add(index(sum[i]),1);
}
printf("%lld\n",ans);
return 0;
}