二分 树状数组 离散化
这题 wa了好多发 最后发现二分从0开始就好了
问了一圈人 就我二分乱搞
题意 就是 给了你 N 长度序列 你选前 I 个 他们和必须小于 M 你可以让其中某些数字变成0
让他们 最后和小于 M (前I个 不包括I)

所以 我考虑 离散化 + 树状数组存对应位置 + 1 和 他们的和
这样一来 就存在单调性 可二分了
二分树状数组 M - A[I]
如果大于 我们 把大于位置之后个数的直接输出就好
然后 在把这个数据补充到树状数组中 对应位置 +1

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;

long long c[maxn];
int num[maxn];
int a[maxn], b[maxn], ct[maxn];
int n, m, t, cpt;

long long queval(int x){
    long long res = 0;
    for(; x; x -= x&(-x)) res += c[x];
    return res;
}

void add(int x, int y){
    for(;x <= n + 1; x += x & (-x)) c[x] += y;
}

void addd(int x, int y){
    for(;x <= n + 1; x += x & (-x)) num[x] += y;
}

int quenum(int x){
    int res = 0;
    for(; x; x -= x&(-x)) res += num[x];
    return res;
}
int que(int x) {
    //cout << queval(x) - queval(x - 1) << endl;
    cout << quenum(n) << "   " << quenum(x) << endl ;
}

bool chk(int mid) {
//    cout << mid << "  sum " << queval(mid) << endl;
    return queval(mid) <= m - cpt; 
}

signed main(){
    scanf("%d", &t);
    while(t --) {
        scanf("%d %d", &n, &m);
        memset(c, 0, (n + 5) * sizeof(long long)) ;
        memset(num, 0, (n + 5) * sizeof(int)) ;
        for(int i = 1; i <= n; i ++) scanf("%d", &a[i]), b[i] = a[i] , ct[i] = 0;
        sort(b + 1, b + 1 + n);
        for(int i = 1; i <= n; i ++) {
            int pos = lower_bound(b + 1, b + 1 + n, a[i]) - b;
            if(ct[pos] == 0) ct[pos] = pos;
            int rt = pos;
            pos = ct[pos];
            ct[rt] = pos + 1;
            cpt = a[i];
        //    cout << pos << endl;    
            int l = 0, r = n + 1;
            while(l < r) {
                int mid = l + r + 1 >> 1;
                if(chk(mid)) l = mid;
                else r = mid - 1;
            } 
            //cout << l << " p    " ;
            printf("%d", quenum(n) - quenum(l)); 
        //    que(l);

             add(pos, a[i]);
            //que(pos);
            addd(pos, 1);
            printf(" ");
        } puts("");
    }
    return 0;
}