题目描述
Given a sequence of n integers called W and an integer m. For each i (1 <= i <= n), you can choose some elements Wk (1 <= k < i), and change them to zero to make So what's the minimum number of chosen elements to meet the requirements above?.
输入
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*105
1 <= m <= 109
For each i, 1 <= Wi <= m
输出
For each test case, you should output n integers in one line: i-th integer means the minimum number of chosen elements Wk (1 <= k < i), and change them to zero to make
样例输入
复制样例数据
2 7 15 1 2 3 4 5 6 7 5 100 80 40 40 40 60
样例输出
0 0 0 0 0 2 3 0 1 1 2 3
用队列实现很难,而且一定会T。用mulitset实现,玄学时长。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll mod=1e9+7;
const int modp=998244353;
const int maxn=2e5+50;
const double eps=1e-6;
#define lowbit(x) x&(-x)
#define INF 0x3f3f3f3f
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline void write(ll x){
if(x<0){
putchar('-');
write(~x+1);
}
else{
if(x>9){
write(x/10);
}
else{
putchar(x%10+'0');
}
}
}
int dcmp(double x)
{
if(fabs(x)<eps)return 0;
return (x>0)?1:-1;
}
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
ll qmod(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
{
ans=(ans*a)%mod;
}
b>>=1;
a=(a*a)%mod;
}
return ans;
}
ll a[maxn],ans[maxn];
multiset<ll> mp;//维护留下的数
multiset<ll>::iterator it;
int main()
{
int t;
scanf("%d",&t);
int n;
ll m;
while(t--){
n=read();
m=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
mp.clear();
mp.insert(a[1]);
ans[1]=0;
ll sum=a[1];
ll now=sum;
for(int i=2;i<=n;i++){
it=mp.end();
it--;
now=sum;
ll maxx=*it;//留下的数中最大的那个
if(sum+a[i]<=m){//如果当前数可以直接留下,插入即可
ans[i]=i-1-mp.size();
mp.insert(a[i]);
sum+=a[i];
}
else{//如果不能直接留下,要判删掉多少
for(int j=mp.size()-1;;it--,j--){
sum-=*it;
if(sum+a[i]<=m){
ans[i]=i-1-j;//留下的数删掉j个,可以把当前数留下
if(a[i]<maxx){//如果当前数大于原留下数的最大值,显然留下当前数,抛弃原最大值
mp.erase(maxx);
mp.insert(a[i]);
now-=maxx;
now+=a[i];
}
sum=now;//now用来更新sum,保证sum始终为选择最优的留下的数的和
break;
}
}
}
}
for(int i=1;i<=n;i++){
printf("%lld ",ans[i]);
}
printf("\n");
}
return 0;
}