★☆★cf D. Petya and Array
http://codeforces.com/problemset/problem/1042/D
抽象成一个问题:一边增加数组长度,增加之后再随机找小于某阈值的数的个数。
树状数组,离散化,模拟运行一遍,找到所有可能出现的值,记录下来,给一个index映射,然后在数值的波动范围上做查找,
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 200005; ll a[MAXN], b[MAXN], bit[2 * MAXN]; int n; int lowbit(int x) { return x & -x; } ll sum(int x) { ll ans = 0; while (x) { ans += bit[x]; x -= lowbit(x); } return ans; } void add(int i, ll x, int maxn) { while (i <= maxn) { bit[i] += x; i += lowbit(i); } } int main() { //freopen("in.txt", "r", stdin); ll t; while (cin >> n >> t) { memset(a, 0, sizeof a); memset(b, 0, sizeof b); memset(bit, 0, sizeof bit); for (int i = 1; i <= n; i++) { cin >> a[i]; b[i] = b[i - 1] + a[i]; } vector<ll> v; for (int i = 0; i <= n; i++) { v.push_back(b[i]); v.push_back(b[i] + t); } sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); map<ll, int> mp; for (int i = 0; i < v.size(); i++) mp[v[i]] = i + 1; ll ans = 0; for (int i = n; i >= 1; i--) { add(mp[b[i]], 1, v.size()); ans += sum(mp[b[i - 1] + t] - 1); } cout << ans << endl; } return 0; }