题目大意:
第二次萌新赛 数对
1.时间复杂度需要控制在 n ∗ l o g n n*logn n∗logn之内
思路:
这道题让我们去求的数对的数量 , 根据
a
l
+
a
l
+
1
+
.
.
.
+
a
r
−
1
+
a
r
<
=
x
+
y
∗
(
r
−
l
+
1
)
a_l + a_{l + 1} + ...+a_{r - 1} +a_r <= x + y *(r - l + 1 )
al+al+1+...+ar−1+ar<=x+y∗(r−l+1) 这个条件我们需要进行一个处理, 将右边第二项移到左边,从整个序列来说我们需要去将每一项都减去y之后再查询新的每一个区间是否满足区间和小于等于
x
x
x 即可.但这个查询如果暴力来做的话会直接超时, 我们可以这样考虑:对于每一个
s
u
m
[
i
]
sum[i]
sum[i]我们将它前面的i - 1 个数都按从大到小的顺序插入到vector容器中(使用low_bound 函数辅助实现) , 那么对于任意一个
j
,
j
<
i
j , j < i
j,j<i 来说 ,题目要求也就是 求
s
u
m
[
i
]
−
s
u
m
[
j
]
<
=
x
sum[i] - sum[j] <= x%
sum[i]−sum[j]<=x , 也就是我们需要求对于未插入容器的
s
u
m
[
i
]
sum[i]
sum[i] 来说 只要求的满足
s
u
m
[
i
]
−
x
<
=
s
u
m
[
j
]
sum[i] - x <= sum[j]
sum[i]−x<=sum[j] 的
j
j
j 的个数就行了。 也就是这样一行代码
res += mp.size() - (lower_bound(mp.begin() , mp.end() , sum[i] - x ) - mp.begin() ) ;
2.需要注意的一些点:
我们需要初始化一下vector容器 , 要先向容器中插入一个0 这是非常容易忽略的一点为什么需要向容器中先加入一个0呢?
对于
s
u
m
[
i
]
−
x
sum[i] - x
sum[i]−x 这个式子来说, 我们考虑一种特殊的情况 , 就是前i个元素的和都小于等于x的话(也就是j = 0 ) 如果不添加这个零的话我们考虑的就只是从1 ~ i 的 的子区间去选而不包括[1, i] 这个最大的区间。 如果添加上0之后我们就能去求解这个满足条件的个数了。
代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std ;
typedef long long LL ;
const LL N = 2e5 + 10 ;
vector<LL> mp ;
LL a[N] , sum[N] ;
LL n , x , y ;
signed main()
{
cin >> n >> x >> y ;
LL res = 0 ;
for(int i = 1; i <= n ; i ++ )
{
cin >> a[i] ;
sum[i] += sum[i - 1] - y + a[i] ;
}
mp.push_back(0) ;
for(int i = 1 ; i <= n ; i ++ )
{
res += mp.size() - (lower_bound(mp.begin() , mp.end() , sum[i] - x ) - mp.begin() ) ;
mp.insert(lower_bound(mp.begin() , mp.end() , sum[i] ) , sum[i] ) ;
}
cout << res << endl ;
return 0 ;
}