Find the answer
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 ∑ij=1Wj<=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*105
1 <= m <= 109
For each i, 1 <= Wi <= m
Output
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 ∑ij=1Wj<=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
题意:
给个长度为n的数组,对于每个i,你可以选择1~i-1中任意多的数并将它删去(把权值变为0),使得(a[1]-a[i])的和小于等于m,问对于每个i最少删几个数可以达到要求
分析:
删除的最少个数=i-1-保留的最多个数
显然优先保留数值较小的数
因此建立权值线段树,维护每个数的个数与总和
题目变为求最多的数使得他们的和小于等于m-a[i],(从小到大选取)
这题还需要离散化
code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxm=2e5+5;
int a[maxm];
int xx[maxm],cnt;
int n,m;
ll val[maxm<<2];
int num[maxm<<2];
void build(int l,int r,int node){
val[node]=num[node]=0;
if(l==r)return ;
int mid=(l+r)/2;
build(l,mid,node*2);
build(mid+1,r,node*2+1);
}
void pushup(int node){
val[node]=val[node*2]+val[node*2+1];
num[node]=num[node*2]+num[node*2+1];
}
void update(int x,int l,int r,int node){
if(l==r){
val[node]+=xx[x];
num[node]++;
return ;
}
int mid=(l+r)/2;
if(x<=mid)update(x,l,mid,node*2);
else update(x,mid+1,r,node*2+1);
pushup(node);
}
int ask(int x,int l,int r,int node){
if(val[node]<=x)return num[node];
if(l==r){//输出需要的个数和拥有的个数中的较小值
return min(num[node],x/xx[l]);//xx[l]是当前节点未离散化的值
}
int mid=(l+r)/2;
if(val[node*2]>=x)return ask(x,l,mid,node*2);
else return num[node*2]+ask(x-val[node*2],mid+1,r,node*2+1);
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
xx[i]=a[i];
}
sort(xx+1,xx+1+n);
cnt=unique(xx+1,xx+1+n)-(xx+1);
build(1,cnt,1);
for(int i=1;i<=n;i++){
printf("%d ",i-1-ask(m-a[i],1,cnt,1));
int p=lower_bound(xx+1,xx+1+cnt,a[i])-xx;
update(p,1,cnt,1);
}
puts("");
}
return 0;
}