赛中队友写的,由于最近一直做到主席树的题,结果一上来就搞了个主席树MLE笑死我了。
题意:给出一组数,对于每个数 a [ i ] a[i] a[i]求出最少删除 i i i 前面多少个数使得前缀和小于等于 m m m。
题解:权值线段树维护以 i i i为右端点的前缀和以及数的个数。 每次查询最多可以取多少个数可以使得前缀和小于等于 m m m,假设为 c n t cnt cnt, 那么最后的答案就是 i − 1 − c n t i-1-cnt i−1−cnt
#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<stack>
#include<ctime>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5 + 5;
const int M = 1e7 + 5;
const int INF = 0x3f3f3f3f;
const ull seed = 11;
const int MOD = 1e9 + 7;
using namespace std;
vector<ll> vv;
ll totSum[maxn << 2];
int sum[maxn << 2];
void build(int l, int r, int rt){
if(l == r){
sum[rt] = 0;
totSum[rt] = 0;
return;
}
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
totSum[rt] = totSum[rt << 1] + totSum[rt << 1 | 1];
sum[rt] = 0;
}
void update(int l, int r, int pos, int rt){
if(l == r){
sum[rt]++;
totSum[rt] += vv[l - 1];
return;
}
int m = (l + r) >> 1;
if(pos <= m)
update(l, m, pos, rt << 1);
else
update(m + 1, r, pos, rt << 1 | 1);
totSum[rt] = totSum[rt << 1] + totSum[rt << 1 | 1];
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
int query(int l, int r, ll k, int rt){
if(l == r){
if(k == 0) return 0;
else if(k >= vv[l - 1]){
return k / vv[l - 1];
}
return 0;
}
int m = (l + r) >> 1;
ll Lsum = totSum[rt << 1];
if(Lsum >= k)
return query(l, m, k, rt << 1);
else
return sum[rt << 1] + query(m + 1, r, k - Lsum, rt << 1 | 1);
}
ll a[maxn];
ll getid(ll x){
return lower_bound(vv.begin(), vv.end(), x) - vv.begin() + 1;
}
int n;
ll m;
int main(){
int T;
scanf("%d", &T);
while(T--){
vv.clear();
scanf("%d%lld", &n, &m);
for(int i = 1; i <= n; i++){
scanf("%lld", &a[i]);
vv.push_back(a[i]);
}
sort(vv.begin(), vv.end());
vv.erase(unique(vv.begin(), vv.end()), vv.end());
build(1, vv.size(), 1);
ll ret = 0;
for(int i = 1; i <= n; i++){
ret += a[i];
if(ret <= m) printf("0 ");
else{
ll tmp = m - a[i];
int ans = query(1, vv.size(), tmp, 1);
ans = i - 1 - ans;
printf("%d ", ans);
}
update(1, vv.size(), getid(a[i]), 1);
}
puts("");
}
return 0;
}