题解思路:对于每个位置,求出需要减掉的数 然后在权值线段树上进行二分找答案。
#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
#define ll long long
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
typedef pair<int,int> PII;
const int mod = 1e9+7;
int n,m;
ll a[maxn],b[maxn],num[maxn<<2],sum[maxn<<2],atag[maxn<<2];
void Pushup(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
num[rt]=num[rt<<1]+num[rt<<1|1];
}
void Build(int l,int r,int rt){
num[rt]=sum[rt]=0;
if(l==r)return ;
int mid=(l+r)>>1;
Build(ls);
Build(rs);
}
void Update(int l,int r,int rt,int pos){
if(l==r&&l==pos){
sum[rt]+=b[pos];
num[rt]++;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid)Update(ls,pos);
else Update(rs,pos);
Pushup(rt);
}
int Query(int l,int r,int rt,ll ss){
if(l==r){
int ans=ss/b[l];
if(ss%b[l])ans++;
return ans;
}
int mid=(l+r)>>1;
if(sum[rt<<1|1]>=ss)return Query(rs,ss);
else{
int ans=num[rt<<1|1];
ans+=Query(ls,ss-sum[rt<<1|1]);
return ans;
}
}
int main()
{
int t;cin>>t;
while(t--){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
int nn=unique(b+1,b+n+1)-(b+1);
Build(1,nn,1);
ll Sum=0;
for(int i=1;i<=n;i++){
Sum+=a[i];
if(Sum<=m){
printf("0 ");
int pos=lower_bound(b+1,b+nn+1,a[i])-b;
Update(1,nn,1,pos);
}
else{
ll ss=Sum-m;
printf("%d ",Query(1,nn,1,ss));
int pos=lower_bound(b+1,b+nn+1,a[i])-b;
Update(1,nn,1,pos);
}
}
printf("\n");
}
}