Codeforces 1042D Petya and Array(线段树)

                                                                               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

一、原题地址

  点我传送

 

二、大致题意

求所有[ l , r ]区间和小于T的这样的区间数量。

 

三、大致思路

记i点的前缀和为sum[ i ]。那么我们所求的区间实际上是满足 sum[ i ]-sum[ j ]<T (i > j)这样的区间。对这个式子做个变换就是sum[ i ] - T< sum[ j ](i > j)。

那么枚举每一个 i ,只需要更新此时有多少个 j 是符合条件的。快速查找之前有多少个 j 符合条件,这可以用树状数组做到。

四、代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<functional>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long LL;
int gcd(int a, int b) { return a == 0 ? b : gcd(b % a, a); }


int n;
LL ans;
LL T;
LL sum[200005],a[200005],f[200005];

const int maxn = 200005;
LL c[maxn];		//用于处理树状数组
int lowbit(int x)
{
	return (x)&(-x);
}
void update_onepos(int pos, LL x)		//单点增加x
{
	while (pos <= n+1)
	{
		c[pos] += x;
		pos += lowbit(pos);
	}
}
LL getsum_onepos(int pos)		//区间求和 [1,x]
{
	LL sum = 0;
	while (pos > 0)
	{
		sum += c[pos];
		pos -= lowbit(pos);
	}
	return sum;
}
void build()
{
	for (int i = 1; i <= n; i++)
	{
		update_onepos(i, 0);
	}
}

int main()
{
	scanf("%d %lld", &n, &T);
	ans = a[0] = 0;
	for (int i = 1; i <= n; i++)
	{
		scanf("%lld", &a[i]);
		sum[i] = a[i] + sum[i - 1];
		f[i] = sum[i];
	}			//读入&求前缀和
	f[0] = 0;
	sort(f, f + 1 + n);
	build();	//建树
	for (int i = 1; i <= n; i++)
	{
		int pos = lower_bound(f, f + n + 1, sum[i - 1]) - f + 1;//找到前一个元素所处的位置
		update_onepos(pos, 1);					//插入上一个元素
		pos = lower_bound(f, f + 1 + n, sum[i] - T + 1) - f;
		ans += (i - getsum_onepos(pos));		//找到当前元素&更新
	}
	printf("%lld\n", ans);

	getchar();
	getchar();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值