★☆★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;
}

猜你喜欢

转载自www.cnblogs.com/waldenlake/p/9754731.html