Given a sequence of n integers called W and an integer m. For each i (1 <= i <= n), you can choose some elements WkWk (1 <= k < i), and change them to zero to make ∑ij=1∑j=1iWjWj<=m. So what's the minimum number of chosen elements to meet the requirements above?.
Input
The first line contains an integer Q --- the number of test cases.
For each test case:
The first line contains two integers n and m --- n represents the number of elemens in sequence W and m is as described above.
The second line contains n integers, which means the sequence W.
1 <= Q <= 15
1 <= n <= 2*105105
1 <= m <= 109109
For each i, 1 <= WiWi <= m
Output
For each test case, you should output n integers in one line: i-th integer means the minimum number of chosen elements WkWk (1 <= k < i), and change them to zero to make ∑ij=1∑j=1iWjWj<=m.
Sample Input
2 7 15 1 2 3 4 5 6 7 5 100 80 40 40 40 60
Sample Output
0 0 0 0 0 2 3 0 1 1 2 3
用一个线段树维护前i-1数的一个子集,保证在数量最多的情况下,总和小于m。这样对于第i个数,如果这个数加上后总和小于m,那就放进这个子集;如果放进去之后超过了,而且这个数比这个子集里面最大数要小,那么放进这个数,去除最大数就好了;如果放进去之后超过而且还比最大数大,那么这个数在后面一定被抛弃,那么直接判断最少用多少数能把她放进去就行了。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 200005;
ll sum[maxn * 4], ma[maxn * 4], num[maxn * 4];
ll sot[maxn], tmp[maxn];
ll n, m;
void pushup(int rt) {
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
ma[rt] = max(ma[rt << 1], ma[rt << 1 | 1]);
num[rt] = num[rt << 1] + num[rt << 1 | 1];
}
void build(int l, int r, int rt) {
sum[rt] = ma[rt] = num[rt] = 0;
if (l == r)return;
int m = (l + r) >> 1;
build(lson); build(rson);
}
void add(int l, int r, int rt, int x, int k) {
//cout << l << " " << r << " " << rt << " " << x << "\n";
if (l == r) {
sum[rt] += sot[x] * k;
num[rt] += k;
if (num[rt] != 0) ma[rt] = sot[l];
else ma[rt] = 0;
return;
}
int m = (l + r) >> 1;
if (x <= m)add(lson, x, k);
else add(rson, x, k);
pushup(rt);
}
ll query(int l, int r, int rt, ll su) {
// cout << l << " " << r << " " << rt << " " << su << "\n";
if (su <= 0)return 0;
if (l == r) {
ll t = ((su - 1) / sot[l]) + 1;
if (t < 0)t = 0;
return t;
}
int m = (l + r) >> 1;
ll res = 0;
if (sum[rt << 1 | 1] >= su) {
res += query(rson, su);
}
else {
res += num[rt << 1 | 1] + query(lson, su - sum[rt << 1 | 1]);
}
return res;
}
int id(ll x) {
return lower_bound(sot + 1, sot + 1 + n, x) - sot;
}
int main() {
int te;
scanf("%d", &te);
while (te--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%lld", &sot[i]);
tmp[i] = sot[i];
}
sort(sot + 1, sot + n + 1);
build(1, n, 1);
ll ans = 0;
for (int i = 1; i <= n; i++) {
ll big = ma[1], asum = sum[1];
if (asum + tmp[i] <= m) {
add(1, n, 1, id(tmp[i]), 1);
printf("%lld", ans); printf(" ");
continue;
}
if (big >= tmp[i]) {
add(1, n, 1, id(big), -1);
add(1, n, 1, id(tmp[i]), 1);
ans++;
printf("%lld", ans); printf(" ");
continue;
}
ll tm = ans;
tm += query(1, n, 1, asum + tmp[i] - m);
printf("%lld", tm); printf(" ");
ans++;
}
printf("\n");
}
return 0;
}
/*
5
5 3
1 2 1 2 1
*/