“加油站”优先队列贪心3题

本文通过三个具体的编程问题,介绍了如何使用优先队列解决特定类型的问题。包括在字符串中匹配括号对的成本最小化问题、从给定序列中选择元素以获得最大价值问题以及调整物品成本以达到最小额外开销问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概括起来就是前m个里一定有n个的问题,可以追溯到很经典的一个题:一辆车经过几个加油站,每个加油站有价格不同的一定量油,开车要消耗油,问至少多少钱到终点。做法就是先假装不加,油不够了再往前面找最便宜的加油站加,用一个优先队列维护即可。这类题的难点在于抽象出这个模型往往隐藏得很深,要看出来才行。

http://codeforces.com/problemset/problem/3/D

#include <bits/stdc++.h>
using namespace std;
char str[50500];
int main()
{
    scanf("%s", str+1);
    int l=strlen(str+1);
    if(l%2!=0){
        printf("-1\n");
        return 0;
    }
    int a, b;
    long long ans=0;
    int sta=0;
    if(str[1]==')'){
        printf("-1\n");
        return 0;
    }
    else if(str[1]=='?'){
        scanf("%d%d", &a, &b);
        ans+=a;
        str[1]='(';
    }
    priority_queue<pair<int, int> >pq;
    for(int i=1;i<l/2;i++){
        if(str[2*i]==')'){
            sta--;
        }
        else if(str[2*i]=='('){
            sta++;
        }
        else {
            scanf("%d%d", &a, &b);
            ans+=b;
            pq.push(make_pair(b-a, 2*i));
            str[2*i]=')';
            sta--;
        }
        if(str[2*i+1]==')'){
            sta--;
        }
        else if(str[2*i+1]=='('){
            sta++;
        }
        else {
            scanf("%d%d", &a, &b);
            ans+=b;
            pq.push(make_pair(b-a, 2*i+1));
            str[2*i+1]=')';
            sta--;
        }
        while(sta<0){
            if(pq.empty()){
                printf("-1\n");
                return 0;
            }
            pair<int, int>tmp=pq.top();
            pq.pop();
            sta+=2;
            ans-=tmp.first;
            str[tmp.second]='(';
        }
    }
    if(sta>0){
        printf("-1\n");
        return 0;
    }
    if(str[l]=='('){
        printf("-1\n");
        return 0;
    }
    else if(str[l]=='?'){
        scanf("%d%d", &a, &b);
        ans+=b;
        str[l]=')';
    }
    printf("%lld\n%s\n", ans, str+1);
}

http://codeforces.com/gym/100956/attachments D

#include <bits/stdc++.h>
using namespace std;
int n;
int a[105000];
int b[105000];
int c[105000];
bool cmp(int x, int y){
    if(a[x]!=a[y])return a[x]>a[y];
    else return b[x]>b[y];
}
int main()
{
    scanf("%d", &n);
    for(int i=1;i<=n;i++)scanf("%d", &a[i]);
    for(int i=1;i<=n;i++)scanf("%d", &b[i]);
    for(int i=1;i<=n;i++)c[i]=i;
    sort(c+1, c+1+n, cmp);
    priority_queue<int, vector<int>, greater<int> >pq;
    long long ans=0;
    for(int i=1;i<=n/2;i++){
        pq.push(b[c[2*i]]);
        if(2*i+1<=n)pq.push(b[c[2*i+1]]);
        else pq.push(0);
        pq.pop();
    }
    while(!pq.empty()){
        ans+=pq.top();
        pq.pop();
    }
    printf("%lld\n", ans);
}

http://codeforces.com/problemset/problem/767/E

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, m;
ll c[105000];
ll w[105000];
ll s[105000];
int main()
{
    scanf("%lld%lld", &n, &m);
    for(int i=1;i<=n;i++)scanf("%lld", &c[i]);
    for(int i=1;i<=n;i++)scanf("%lld", &w[i]);
    ll dis=0;
    priority_queue<pair<ll, ll>, vector<pair<ll, ll> >, greater<pair<ll, ll> > >pq;
    for(int i=1;i<=n;i++){
        if(c[i]%100==0){
            s[i]=c[i]/100;
        }
        else{
            s[i]=c[i]/100;
            m-=(c[i]-s[i]*100);
            pq.push(make_pair(w[i]*(100-c[i]+s[i]*100),i));
            if(m<0){
                m+=100;
                pair<ll, ll> tmp=pq.top();
                pq.pop();
                dis+=tmp.first;
                s[tmp.second]++;
            }
        }
    }
    printf("%lld\n", dis);
    for(int i=1;i<=n;i++){
        printf("%lld ", s[i]);
        if(s[i]*100<c[i])printf("%lld\n", c[i]-s[i]*100);
        else printf("0\n");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值