Find the answer HDU - 6609 (权值线段树)

84 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

 题意:

链接:SDNU多校组队赛(第3,4场) - Virtual Judge

Q组样例,给你 n 个数,和一个上限值 m ,让你求在第 i 个位置时,为了使前 i 个数的和(包括第 i 个数)不超过 m ,问你最少删除第 i 个数之前的几个数(不可以删除第 i 个数)。让你把 i 取 1 - n 时都输出出来。(1<=n<=2*10^5  1<=m<=10^9  1<= wi <= m)

解题思路:

首先要删除就删除第 i 个元素之前的尽可能大的,这样才删除的元素少。同时要保证: 删出的总和 >= sum - m ,那么怎么满足 (删出的总和 >= sum - m ) 同时要求出珊哪些?删除多少元素呢? 这时就可以使用权值线段树来维护,右节点如果小于 sum - m,就全要并且接着往左孩子找,否者往右孩子找下去。

AC代码:

#include<bits/stdc++.h>
#define up(i, x, y) for(ll i = x; i <= y; i++)
#define down(i, x, y) for(ll i = x; i >= y; i--)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define IO ios::sync_with_stdio(false),cin.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-8;
const ll mod = 1e9 + 7;
const ll maxn = 2e5 + 7;
const double pi = acos(-1);
const ll inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
using namespace std;

ll Q, n, m;
int a[maxn], b[maxn];
struct node
{
    ll l, r, val, time;
}t[maxn * 4];

void build(ll k, ll l, ll r)
{
    t[k].l = l, t[k].r = r;
    t[k].val = 0, t[k].time = 0;
    if(l == r)
    {
        return ;
    }
    ll mid = (l + r) >> 1;
    build(k << 1, l, mid);
    build(k << 1 | 1, mid + 1, r);
}
void update(ll k, ll l, ll r, ll x)
{
    if(t[k].l >= l && t[k].r <= r)
    {
        t[k].val += x;
        t[k].time ++ ;
        return ;
    }
    ll mid = (t[k].l + t[k].r) >> 1;
    if(l <= mid) update(k << 1, l, r, x);
    if(mid + 1 <= r) update(k << 1 | 1, l, r, x);
    t[k].val = t[k << 1].val + t[k << 1 | 1].val;
    t[k].time = t[k << 1].time + t[k << 1 | 1].time;
}

void query(ll k, ll val, ll &ans)
{
//    debug(k);

    if(t[k].l == t[k].r)
    {
        if(val % b[t[k].l] == 0) ans += val / b[t[k].l];
        else ans += val / b[t[k].l] + 1;  //注意需要向上取整,因为要大于等于 sum - m
        return ;
    }
    if(t[k << 1 | 1].val >= val)
    {
        query(k << 1 | 1, val, ans);
    }
    else
    {
        ans += t[k << 1 | 1].time;
        val -= t[k << 1 | 1].val;
        query(k << 1, val, ans);
    }
}

int main()
{
    scanf("%lld", &Q); while(Q--)
    {
        ll sum = 0;
        scanf("%lld %lld", &n, &m);
        for(ll i = 1; i <= n; i++)
        {
            scanf("%lld", &a[i]);
            b[i] = a[i];
        }
        sort(b + 1, b + 1 + n);
        ll len = unique(b + 1, b + 1 + n) - (b + 1);
//        debug(len);
        build(1, 1, len);
        for(ll i = 1; i <= n; i++)
        {
            sum += a[i];
            if(i == 0) printf("0 ");
            else
            {
                ll ans = 0;
                if(sum <= m)
                    ans = 0;
                else
                    query(1, sum - m, ans);

                printf("%lld ", ans);
            }
            ll loc = lower_bound(b + 1, b + 1 + len, a[i]) - b;
            update(1, loc, loc, a[i]);
        }
        puts("");
    }
}