P2073 送花

原题链接  https://www.luogu.com.cn/problem/P2073

 

 题解

团队作业中【平衡树应用】的一道题目,但读完题目后觉得可以直接模拟,不用平衡树做;

题目中只有一种添加操作和两种删除操作,而且两种删除操作是分别删除一个最大值或最小值,那么我们很快就可以想到可以用两个堆(大根堆和小根堆)来分别维护最大值和最小值;

每次删除一个最大值或最小值时,我们就取大根堆或小根堆的堆顶将其删除就好,至于怎么判断一种花有没有被删除,我们可以将其美丽值赋为 $0$ 就好了;

还有就是注意到了题目中说道 “ 如果加入的花朵价格已经与花束中已有花朵价格重复,则这一朵花不能加入花束。”,也就是说一个价格对应了一个美丽值,所以我们可以开一个数组:$v [ i ]$ 来表示价格为 i 的花束对应的美丽值是多少;

剩下需要注意的细节代码中有注释:

$Code$:

#include <bits/stdc++.h>
#define maxn 1000001
using namespace std;
int v[maxn];              //v[i]:价格为i的话美丽值是多少  
long long beauty,value;
priority_queue<int,vector<int>,less<int> > qmin;    //小根堆 
priority_queue<int,vector<int>,greater<int> >qmax;  //大根堆 
void Add()                //添加一朵花 
{
    int x,y;
    cin>>x>>y;            //美丽值为x,价格为y 
    if (v[y]) return;     //重复价格的花束不能添加 
    qmin.push(y);         //注意是将价格y入堆 
    qmax.push(y);
    v[y]=x;
    beauty+=x,value+=y;   //直接算出现有花束的美丽值和价格的总和,方便询问时直接输出 
}
void Delin()              //删除一个价格最小的花束 
{
    while(!qmin.empty()&&v[qmin.top()]==0) qmin.pop();  //注意要先将已经删除了的花束(美丽值为0)弹出堆 
    if (!qmin.empty())
    {
        int now=qmin.top(); //now记录价格最小的花束的价格 
        beauty-=v[now];   //更新总美丽值 
        value-=now;       //更新总价格 
        v[now]=0;         //将其删除,美丽值设为0 
        qmin.pop();       //弹出now 
    }
}
void Delax()              //删除一个价格最大的花束
{
    while(!qmax.empty()&&v[qmax.top()]==0) qmax.pop();  //注意要先将已经删除了的花束(美丽值为0)弹出堆 
    if (!qmax.empty())
    {
        int now=qmax.top(); //now记录价格最小的花束的价格
        beauty-=v[now];   //更新总美丽值 
        value-=now;       //更新总价格 
        v[now]=0;         //将其删除,美丽值设为0 
        qmax.pop();       //弹出now 
    }
}
int main()
{
    int q;
    cin>>q;
    while(q!=-1)
    {
        if (q==1) Add();
        if (q==2) Delin();
        if (q==3) Delax();
        cin>>q;
    }
    cout<<beauty<<" "<<value;
    return 0;
}
原文地址:https://www.cnblogs.com/xcg123/p/12819420.html