
const int N = 40005;
class SegmentTree {
public:
struct {
int val;
int l, r;
}tree[N];
inline int ls(int root)
{
return root << 1;
}
inline int rs(int root)
{
return (root << 1) + 1;
}
void build(int root, int left, int right)
{
tree[root].l = left;
tree[root].r = right;
tree[root].val = 0;
if (left == right) {
return;
}
int mid = (left + right) >> 1;
build(ls(root), left, mid);
build(rs(root), mid + 1, right);
}
int query(int root, int left, int right)
{
if (tree[root].l == left and tree[root].r == right) {
return tree[root].val;
}
int mid = (tree[root].l + tree[root].r) >> 1;
if (right <= mid) {
return query(ls(root), left, right);
}
else if (left > mid) {
return query(rs(root), left, right);
}
else {
return query(ls(root), left, mid) + query(rs(root), mid + 1, right);
}
}
void insert(int root, int pos)
{
++tree[root].val;
if (tree[root].l == tree[root].r)
return;
int mid = (tree[root].l + tree[root].r) >> 1;
if (pos <= mid) {
insert(ls(root), pos);
}
else {
insert(rs(root), pos);
}
}
};
class Solution {
public:
using ll = long long;
ll preSum[N];
vector<ll> vals;
SegmentTree tree;
ll find(ll x)
{
return lower_bound(vals.begin(), vals.end(), x) - vals.begin();
}
int countRangeSum(vector<int> nums, int lower, int upper)
{
int n = (int)nums.size();
for (int i = 1; i <= n; ++i) {
preSum[i] = preSum[i - 1] + nums[i - 1];
}
for (int i = 0; i <= n; ++i) {
vals.push_back(preSum[i]);
vals.push_back(preSum[i] - lower);
vals.push_back(preSum[i] - upper);
}
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
int res = 0;
tree.build(1, 1, vals.size());
for (int i = 0; i <= n; ++i) {
ll l_bound = preSum[i] - upper, r_bound = preSum[i] - lower;
res += tree.query(1, find(l_bound + 1), find(r_bound + 1));
tree.insert(1, find(preSum[i]) + 1);
}
return res;
}
};