Description
Solution
我们把原序列都减掉\(k\),然后问题就转化为求有多少个连续子序列的和大于等于\(0\)。
求出新序列\(\{b_i\}\)的前缀和\(\{s_i\}\),那么即求有多少对\((i,j)(i\le{j})\)满足\(s[j]-s[i-1]\ge{0}\)。即\(s[j]\ge{s[i-1]}\)。
又\(i\le{j}\),所以\(i-1<j\),问题转化为求顺序对的个数。
然后要注意\(i-1\)可能取到\(0\),所以之前要单独统计一遍\(\forall{i},s[i]\ge{0}\)。(思想:因为\(s[0]\)不好统计,所以把它单独拿出来算,又\(s[0]=0\),所以直接算\(\ge{0}\)个数)。因为是\(i-1<j\),所以要先\(ask\)再\(add\)。
Code
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) ((x) & (-x))
#define ll long long
int n, k, a[200005], c[200005];
ll res, sum[200005], p[200005], r[200005];
int read()
{
int x = 0, fl = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
return x * fl;
}
void add(int x, ll d)
{
while (x <= n)
{
c[x] += d;
x += lowbit(x);
}
return;
}
int ask(int x)
{
int s = 0;
while (x)
{
s += c[x];
x -= lowbit(x);
}
return s;
}
int main()
{
// freopen("3.in", "r", stdin);
n = read(), k = read();
for (int i = 1; i <= n; i ++ )
{
a[i] = read();
sum[i] = sum[i - 1] + (ll)(a[i]);
r[i] = sum[i] - 1ll * i * k;
p[i] = sum[i] - 1ll * i * k;
res += (r[i] >= 0);
}
sort(p + 1, p + n + 1);
int t = unique(p + 1, p + n + 1) - p - 1;
for (int i = 1; i <= n; i ++ )
r[i] = lower_bound(p + 1, p + t + 1, r[i]) - p;
for (int i = 1; i <= n; i ++ )
{
res += ask(r[i]);
add(r[i], 1);
}
printf("%lld\n", res);
return 0;
}