Codeforces Round #510 (Div. 2) D. Petya and Array
Codeforces Round #510 (Div. 2) D. Petya and Array
Petya has an array a consisting of n 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 t. Help Petya to calculate this number.
More formally, you are required to calculate the number of pairs l,r (l≤r) such that a l + a l + 1 + ⋯ + a r < t a_l+a_{l+1}+\cdots+a_r<t al+al+1+⋯+ar<t.
Input
The first line contains two integers n and t (1≤n≤200000,|t|≤2e14).
The second line contains a sequence of integers a1,a2,…,an (|ai|≤1e9) — 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 t.
Examples
input
5 4
5 -1 3 4 -1
output
5
input
3 0
-1 2 -3
output
4
input
4 -1
-2 1 -2 3
output
3
题意非常简单,找 1-n 内有多少个区间的和小于
t
t
t,我们稍加转化:
a
l
+
a
l
+
1
+
⋯
+
a
r
<
t
a_l+a_{l+1}+\cdots+a_r<t
al+al+1+⋯+ar<t
则:
s
u
m
[
r
]
−
s
u
m
[
l
−
1
]
<
t
sum[r]-sum[l-1]<t
sum[r]−sum[l−1]<t
s
u
m
[
r
]
−
s
u
m
[
l
−
1
]
≤
t
−
1
sum[r]-sum[l-1]\leq t-1
sum[r]−sum[l−1]≤t−1
s
u
m
[
r
]
≤
s
u
m
[
l
−
1
]
+
t
−
1
sum[r]\leq sum[l-1]+t-1
sum[r]≤sum[l−1]+t−1
可以预处理出前缀和,题目就转化为对某个数
x
x
x,找小于等于
x
+
t
−
1
x+t-1
x+t−1 的元素个数,快速找区间内小于等于某个数的个数很容易想到权值线段树,这题因为数据量的问题必须要离散化,用一个
v
e
c
t
o
r
vector
vector 存所有前缀和,那么每个前缀和的下标就是他们离散后在线段树中的下标,那么题目就是对每一个前缀和查询符合条件的前缀和个数即可。注意
v
e
c
t
o
r
vector
vector 中的元素必须去重,因为权值线段树保留了上一次插入的状态,如果不去重答案会有重复,AC代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+5;
int n,m,k;
ll t,a[N],sum[N],tree[N<<2];
vector<ll>v;
int getpos(ll x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void pushup(int i)
{
tree[i]=tree[i<<1]+tree[i<<1|1];
}
void build(int i,int l,int r)
{
if(l==r)
{
tree[i]=0;
return ;
}
int mid=l+r>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
pushup(i);
}
void update(int i,int l,int r,int x,int k)
{
if(l==r)
{
tree[i]+=k;
return ;
}
int mid=l+r>>1;
if(x<=mid) update(i<<1,l,mid,x,k);
else update(i<<1|1,mid+1,r,x,k);
pushup(i);
}
ll query(int i,int l,int r,int m,int n)
{
if(m<=l&&r<=n) return tree[i];
int mid=l+r>>1;
ll ans=0;
if(m<=mid) ans+=query(i<<1,l,mid,m,n);
if(n>mid) ans+=query(i<<1|1,mid+1,r,m,n);
return ans;
}
int main(){
scanf("%d%lld",&n,&t);
v.push_back(t-1);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
v.push_back(sum[i]);
v.push_back(sum[i]+t-1);
}
if(n==1){
if(a[1]<t) printf("1");
else printf("0");
}else{
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
m=v.size();
build(1,1,m);
ll ans=0;
for(int i=n;i>=0;i--){
ans+=query(1,1,m,1,getpos(sum[i]+t-1));
update(1,1,m,getpos(sum[i]),1);
}
printf("%lld\n",ans);
}
return 0;
}
推荐阅读
-
Educational Codeforces Round 97 (Rated for Div. 2) D. Minimal Height Tree
-
Codeforces Round #665 (Div. 2) D. Maximum Distributed Tree(dfs)
-
Codeforces Round #619 (Div. 2) D. Time to Run
-
Codeforces Round #583 (Div. 1 + Div. 2,) D. Treasure Island(dfs+思维)
-
Codeforces Round #533 (Div. 2) D. Kilani and the Game(bfs+模拟)
-
Codeforces Round #643 (Div. 2) D. Game With Array
-
Codeforces Round #459 (Div. 2):D. MADMAX(记忆化搜索+博弈论)
-
Codeforces Round #260 (Div. 2) D. A Lot of Games(树上博弈)
-
Codeforces Round #662 (Div. 2) D. Rarity and New Dress
-
Codeforces Round #658 (Div. 2) D. Unmerge(dp,01背包)