1 条题解

  • 1
    @ 2025-8-27 21:23:09

    首先我们发现总金额sum分为2个部分,分别是i=1kapi\sum_{i=1}^{k} a_\text{pi}max(bpi)max(b_\text{pi})。我们发现,单独求出i=1kapi\sum_{i=1}^{k} a_\text{pi}max(bpi)max(b_\text{pi})是很简单的。

    所以我们对bib_i进行升序排序,再从小到大枚举kink\leq i\leq n,令bib_i为当前的max(bpi)max(b_\text{pi})。此时max(bpi)max(b_\text{pi})已经是个定值,所以我们只要求出11~iis=j=1kapjs=\sum_{j=1}^{k} a_\text{pj}的值就行了。 最后答案就等于max(si+bi),kinmax(s_i+b_i),k\leq i\leq n

    那我们该如何动态维护s呢,很简单,用大根堆维护就行,大根堆存放的是所选的物品的价格,如果当前价格小于堆中的最大价格,就执行出堆和aia_i进堆,同时维护s就行了。

    PS:记得多测要清空(主播卡这调了好久)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define pii pair<long long,long long>
    #define x first
    #define y second
    const int N=1e6+10;
    pii a[N];
    int s;
    int n,k;
    priority_queue<int>now;
    bool cmp(pii a,pii b){
    	return a.y<b.y;
    }
    signed main(){
    	int T;
    	scanf("%lld",&T);
    	while(T--){
    		while(now.size())now.pop();
    		s=0;
    		scanf("%lld%lld",&n,&k);
    		for(int i=1;i<=n;i++)scanf("%lld",&a[i].x);
    		for(int i=1;i<=n;i++)scanf("%lld",&a[i].y);
    		sort(a+1,a+1+n,cmp);
    		for(int i=1;i<=k;i++){
    			s+=a[i].x;
    			now.push(a[i].x);
    		}
    		int ans=s+a[k].y;
    		for(int i=k+1;i<=n;i++){
    			if(now.top()>a[i].x){
    				s=s-now.top()+a[i].x;
    				now.pop();
    				now.push(a[i].x);
    			}
    			ans=min(ans,s+a[i].y);
    		}
    		printf("%lld\n",ans);
    	}
    	return 0;
    }
    
    
    • 1

    信息

    ID
    925
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    (无)
    递交数
    87
    已通过
    12
    上传者