Educational Codeforces Round 62 (Rated for Div. 2) C 贪心 + 优先队列 + 反向处理

https://codeforces.com/contest/1140/problem/C

题意

每首歌有(t_i)(b_i)两个值,最多挑选m首歌,使得sum((t_i))*min((b_i))最大

题解

  • 假如最小的(b_i)确定了,那么拿得越多越好
  • 枚举最小的(b_i)然后取剩下最大的(t_i)
  • 两种做法
    1.从(b_i)大向小扫,这样用优先队列维护最大的那些(t_i)(丢弃最小的)
    2.用两个优先队列模拟

代码

//做法1
#include<bits/stdc++.h>
#define ll long long 
#define pii pair<ll,ll>
#define ft first
#define se second
using namespace std;
priority_queue<ll,vector<ll>,greater<ll>  >Q;
pii p[300005];
ll ans,sum;
int n,k;
int main(){
	cin>>n>>k;
	for(int i=0;i<n;i++)scanf("%lld%lld",&p[i].se,&p[i].ft);
	sort(p,p+n,greater<pii>());
	for(int i=0;i<k;i++){
		Q.push(p[i].se);
		sum+=p[i].se;
		ans=max(ans,sum*p[i].ft);
	}
	for(int i=k;i<n;i++){
		ll mi=Q.top();
		if(p[i].se<=mi)continue;
		else{
			Q.pop();
			Q.push(p[i].se);
			sum+=p[i].se-mi;
			ans=max(ans,sum*p[i].ft);
		}
	}
	cout<<ans;
}
//做法2
#include<bits/stdc++.h>
#define ll long long 
#define pii pair<ll,ll>
#define mk make_pair
#define ft first
#define se second
using namespace std;
struct N{
    ll t,d;
}p[300005];
ll n,k,ans,i,tim;
struct cmp{
    bool operator() (pii a, pii b ){
        if(a.ft==b.ft)return a.se>b.se;
        return a.ft>b.ft;
    }
};
bool cmp1(N x,N y){
    return x.d<y.d;
}
priority_queue<pii,vector<pii>,cmp> s;
priority_queue<pii>q;

int main(){
        cin>>n>>k;
    for(i=1;i<=n;i++){
        scanf("%lld%lld",&p[i].t,&p[i].d);
        q.push(mk(p[i].t,p[i].d));
    }
    sort(p+1,p+n+1,cmp1);
    tim=0;
    for(i=1;i<=n;i++){
        while(!s.empty()&&s.top().ft<p[i].d){
            //cout<<"s "<<s.top().se<<endl;
            tim-=s.top().se;s.pop();
        }
        ans=max(ans,p[i].d*tim);
        while(!q.empty()&&s.size()<k){
            //cout<<"q "<<q.top().ft<<endl;
			if(q.top().se>=p[i].d){
            tim+=q.top().ft;
            s.push(mk(q.top().se,q.top().ft));
			}
            q.pop();
            ans=max(ans,p[i].d*tim);
        }
    }
    cout<<ans;
}
原文地址:https://www.cnblogs.com/VIrtu0s0/p/10629300.html