本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题意:
链接: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("");
}
}