离散化 + 树状数组
求解所有元素之和不小于k的非空区间数量:
- 求解前缀和
- 对前缀和进行排序然后离散化
- 树状数组维护小于s[i] - k的值的数量
因为树状数组需要查询小于s[i] - k的数量,所以离散化时需要把每个s[i] - k一起排序离散化
add(get(0), 1) 把0首先加入树状数组,因为从开头到某一个元素也可能是一个满足条件的区间
因为s[i] - k也加入离散化,树状数组开到2 * n
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include "bits/stdc++.h"
using namespace std;
#define ios { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); }
#define fios ofstream out("test.txt");cout.rdbuf(out.rdbuf())
#define endl "\n"
#define lowbit(x) (x & (-x))
#define INF 0x3f3f3f3f
#define MINF 2147483647
#define eps 1e-6
#define PI acos(-1)
typedef long long LL;
typedef pair<int, int> PII;
#define x first
#define y second
const int N = 200010;
int n;
LL k;
int a[N];
LL s[N], tr[N];
vector<LL> alls;
void add(int x, int c)
{
for(int i = x; i <= N; i += lowbit(i))
tr[i] += c;
}
int query(int x)
{
int res = 0;
for(int i = x; i; i -= lowbit(i))
res += tr[i];
return res;
}
int get(LL x)
{
int l = 0, r = alls.size();
while(l < r)
{
int mid = l + r >> 1;
if(alls[mid] >= x) r = mid;
else l = mid + 1;
}
return l + 1;
}
int main()
{
ios;
cin >> n >> k;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
for(int i = 1; i <= n; i++) alls.push_back(s[i]), alls.push_back(s[i] - k);
sort(alls.begin(), alls.end());
alls.erase(unique(alls.begin(), alls.end()), alls.end());
LL res = 0;
add(get(0), 1);
for(int i = 1; i <= n; i++)
{
res += query(get(s[i] - k));
add(get(s[i]), 1);
}
cout << res << endl;
return 0;
}