HDU多校联赛2019Round3. 1007(HDU6609) Find the answer 题解

原题链接:Find the answer
题目大意:给你(n)个数,每一个数不超过(m),对于每一个数(a_i),你要从(a_1,a_2,...,a_{i-1})中删掉一些数,使得 $$ {{sum_{j=1}^i {a_j}} leq m} $$,求对于每一个(i in [1,n]),求要删掉的数的最小数量。
题解:我们先考虑只有一次询问的情况,肯定是贪心,将最大的删去,一次的复杂度为(O(n))(n)次的复杂度便为(O(n^2)),但是,这是每一次重新算,我们发现,在大部分情况下,第(i)个删除的数与第(i+1)个删除的数有很大部分是一样的,改变就是新增的(a_i),所以我们就可以考虑莫队算法,至于维护序列有序,可以用set来完成,复杂度不大靠谱,但是能过。
代码:

#include <set>
#include <cstdio>
using namespace std;
#define Maxn 200000
#define ll long long
int w[Maxn+5];
int n,m;
multiset<int> st;
int main(){
	int t;
	scanf("%d",&t);
	ll sum;
	multiset<int>::iterator it_1;
	int ans;
	while(t--){
		st.clear();
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++){
			scanf("%d",&w[i]);
		}
		sum=0;
		printf("0 ");
		st.insert(w[1]);
		sum+=w[1];
		it_1=st.end();
		ans=0;
		for(int i=2;i<=n;i++){
			sum+=w[i];
			while(sum>m){
				it_1--;
				ans++;
				sum-=(*it_1);
			}
			printf("%d ",ans);
			st.insert(w[i]);
			if(it_1!=st.end()&&w[i]>=(*it_1)){
				sum-=w[i];
				ans++;
				while(sum+(*it_1)<=m){
					sum+=(*it_1);
					ans--;
					it_1++;
				}
			}
		}
		puts("");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/withhope/p/11268580.html