D. Petya and Array
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Petya has an array aa consisting of nn integers. He has learned partial sums recently, and now he can calculate the sum of elements on any segment of the array really fast. The segment is a non-empty sequence of elements standing one next to another in the array.
Now he wonders what is the number of segments in his array with the sum less than tt. Help Petya to calculate this number.
More formally, you are required to calculate the number of pairs l,rl,r (l≤rl≤r) such that al+al+1+⋯+ar−1+ar<tal+al+1+⋯+ar−1+ar<t.
Input
The first line contains two integers nn and tt (1≤n≤200000,|t|≤2⋅10141≤n≤200000,|t|≤2⋅1014).
The second line contains a sequence of integers a1,a2,…,ana1,a2,…,an (|ai|≤109|ai|≤109) — the description of Petya's array. Note that there might be negative, zero and positive elements.
Output
Print the number of segments in Petya's array with the sum of elements less than tt.
Examples
input
Copy
5 4 5 -1 3 4 -1
output
Copy
5
input
Copy
3 0 -1 2 -3
output
Copy
4
input
Copy
4 -1 -2 1 -2 3
output
Copy
3
Note
In the first example the following segments have sum less than 44:
- [2,2][2,2], sum of elements is −1−1
- [2,3][2,3], sum of elements is 22
- [3,3][3,3], sum of elements is 33
- [4,5][4,5], sum of elements is 33
- [5,5][5,5], sum of elements is −1−1
这一题题目是求一个序列,
找出区间和小于t的总区间数。
我们可以构造前缀数组,题目就转换为了sum[j]-sum[i-1]<t,求i、j的对数。
即sum[j]-t<sum[i-1];j>i-1;
这个形式是不是很熟悉,对了 就是我上一篇博客里才学的树状数组求逆序对的结构。。。
卧槽,,大佬就是厉害,看到问题的本质。
这一题就是模拟求逆序对的过程,不过多了一个坑,就是加一个虚节点0,因为这样才能求第1个节点。
#include<bits/stdc++.h>
#define lowbit(x) x&(-x)
using namespace std;
typedef long long ll;
const int M = 500000+100;
ll n,C[M],B[M],A[M];
void add(ll x)
{
while(x<=n+1)//不要忘了我们有个虚节点0,总节点数是n+1;
{
C[x]++;
x+=lowbit(x);
}
}
ll query(ll x)
{
ll ans=0;
while(x)
{
ans+=C[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
ll t,x;
scanf("%lld%lld",&n,&t);
for(int i=1;i<=n;i++)
scanf("%lld",&x),A[i]=A[i-1]+x,B[i]=A[i];//求前缀数组
sort(B,B+1+n);
ll ans=0;
for(int i=1;i<=n;i++)
{
int w=lower_bound(B,B+1+n,A[i-1])-B+1;//
add(w);
int q=lower_bound(B,B+1+n,A[i]-t+1)-B;
ans+=i-query(q);
}
printf("%lld\n",ans);
return 0;
}