题目:
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
题目大意
对于每一个数Ai,在1~i-1删除最少的数,使得SUMi小于m
思路:
先离散化建权值线段树,然后在权值线段树里面求得那个最大的权值就行。
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int maxn = 200005;
int Sum[maxn<<2];
long long totSum[maxn<<2];
int num[maxn];
vector<int>v;
int getid(int value)
{
return lower_bound(v.begin(),v.end(),value)-v.begin()+1;
}
void update(int pos,int l, int r,int rt)
{
if(l==r)
{
Sum[rt]+=1;
totSum[rt]+=v[pos-1];
return ;
}
int mid = (l+r)/2;
if(mid>=pos)update(pos,l,mid,rt<<1);
else update(pos,mid+1,r,rt<<1|1);
Sum[rt] = Sum[rt<<1]+Sum[rt<<1|1];
totSum[rt] = totSum[rt<<1]+totSum[rt<<1|1];
}
int query(int l, int r, int rt, int res)
{
// cout << l<<" "<<r<<" "<<rt<<" "<<res<<endl;
if(l==r)
{
return res/v[l-1];
}
long long sum = totSum[rt<<1];
// cout << sum<<endl;
int mid = (l+r)/2;
if(sum>=res)
return query(l,mid,rt<<1,res);
else
return Sum[rt<<1]+query(mid+1,r,rt<<1|1,res-totSum[rt<<1]);
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n, m;
scanf("%d%d", &n, &m);
v.clear();
for(int i = 1; i <= n; i++)
{
scanf("%d", &num[i]);
v.push_back(num[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
int sz = v.size();
memset(Sum,0,sizeof(int)*sz*4+2);
memset(totSum,0,sizeof(long long)*sz*4+2);
long long tot = 0;
for(int i = 1; i <= n; i++)
{
tot+=num[i];
if(tot<=(long long)m)
printf("0 ");
else
{
int ans = query(1,sz,1,m-num[i]);
printf("%d ", i-ans-1);
}
update(getid(num[i]),1,sz,1);
}
printf("\n");
}
return 0;
}