codeforces round 1086 B题

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int n,p,k,m;
int T;
int a[N];
int main()
{
	cin>>T;
	while(T--)
	{
		cin>>n>>k>>p>>m;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
		}
		multiset<int> opt;
		for(int i=1;i<=k-1;i++)
		{
			opt.insert(a[i]);
		}
		for(int i=k;i<=p-1;i++)
		{
			opt.insert(a[i]);
			m-=*opt.begin();
			opt.erase(opt.begin());
		}
		m-=a[p];
		if(m<0)
		{
			cout<<0<<endl;
			continue;
		}
		long long sum=a[p];
		opt.clear();
		for(int i=1;i<=n;i++)
		{
			if(i!=p)
			{
				opt.insert(a[i]);
			}
			
		}
		for(int i=1;i<=n-k;i++)
		{
			sum+=*opt.begin();
			opt.erase(opt.begin());
		}
		cout<<1+m/sum<<endl; 
		
	}
	
	
	return 0;	
} 

解析:一:multiset是可以排好序的要积累,我们要调用开头的值就用*opt.begin(),如果要删除就opt.erase(地址:例如opt.begin()),
二、这里面最巧妙地点是因为p位置是一定要单独考虑的,所以前k个里面的最小值必定是前n-k名,而p从结尾到前k个也需要消耗n-k次。所以每次就是a[p]+sum[n-k],假设升序排列。你先把第一次处理完下一次除一下就可以了。一定要在纸币上实验,来发现隐藏的规律。

posted @ 2026-03-20 01:06  曾翎一  阅读(1)  评论(0)    收藏  举报