G2-11 wls要吃饭 (25 分) ( priority_queue或者multiset都可以)

G2-11 wls要吃饭 (25 分)

群友们经常喊wls吃饭,但是wls很忙经常忘记。又因为他没有女朋友,也没有练成一个人去商场吃饭的本领。

所以他就买了很多面包。每个面包都有能量。 每天wls早上都会买一个面包,但是他不一定记得吃。

需要群友提醒,群友只会在晚上提醒,每次提醒的时候,wls都会从他当前所有面包里面挑出一个,然后吃掉。但这是他想起了AA姐说的要减肥。所以只挑最小的。

(如果没有面包了,wls没有办法,只能饿肚子了)

输入格式:

第一行两个数n,m(m<=n) 下一行n个数a1,a2,a3......an. ai​表示第i天wls买的面包包含的能量。

再下一行m个数字b1,b2.....bn表示第i个群友在bi​天提醒wls吃饭

1<=ai​,<=1001<=bi​<=n,<=1e5

输出格式:

输出wls总共获得了多少能量

输入样例:

在这里给出一组输入。例如:

5 2
5 4 3 2 1
3 4

输出样例:

在这里给出相应的输出。例如:

5

时间限制   1000 ms

代码如下:

主要是需要一个可以储存可重复数字并排序的容器 (排序时间复杂度为logn)

若排序方法时间复杂度高则容易超时

优先队列priority_queue:

#include<bits/stdc++.h>
using namespace std;
int n , m , last=1;
int bread[100005] , qy[100005];
long long power;
priority_queue<int ,vector<int>,greater<int> > que;
int main()
{

    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>bread[i];
    for(int i=1;i<=m;i++)
        cin>>qy[i];
    for(int i=1;i<=m;i++)//对于每次朋友提醒,找已买面包的最小值
    {
        for(int j=last;j<=qy[i];j++)/从上一次被提醒之后的1天买的面包,到这次被提醒这天买的面包,把面包加入到priority_queue中
        {
        {
            que.push(bread[j]);//priority_queue可以保持排序,并保证每次插入的时间是logN
        }
        if(!que.empty()) //没有面包则不用处理
        {
            power+=que.top();//获得优先队列的第一个元素就是最小元素了,即最小的面包
            que.pop();//把已吃的面包的从priority_queue里面去掉
        }
        last=qy[i]+1;//为下一轮循环作准备
    }
    cout<<power<<endl;
    return 0;
}

 multiset:以下为老师给的代码

#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
int main()
{
    int n,m,i,j,k,mina,next=1,last,sum=0;
    int a[100005];
    int b[100005];
    //multiset可以保持排序,且支持重复元素,并且保证每次插入的时间是logN。或者用map来处理也可以
    multiset<int> s;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(j=1;j<=m;j++)
    {
        cin>>b[j];
    }
    //sort(b+1,b+1+m); //题目貌似b[i]本身就是从小到大的,不用排序。
    for(j=1;j<=m;j++)  //对于每次朋友提醒,找已买面包的最小值
    {
        last=b[j];
        for(k=next;k<=last;k++) //从上一次被提醒之后的1天买的面包,到这次被提醒这天买的面包,把面包加入到multiset中
        {
            s.insert(a[k]); //multiset可以保持排序,并保证每次插入的时间是logN
        }
        if(!s.empty()) //如果还有面包
        {
            mina = *s.begin(); //获得multiset的第一个元素就是最小元素了,即最小的面包
            s.erase(s.begin()); //把已吃的面包的从multiset里面去掉(注意要删除指定位置的元素,而不能用s.erase(mina)这样如果有重复会都删掉)
        }
        else  //如果已没有面包
        {
            mina=0;
        }
        sum += mina; //累加

        next=k; //为下一轮循环作准备
    }
    cout<<sum<<endl;
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值