2015年山东省第六届ACM大学生程序设计竞赛-B-Lowest Unique Price

Link:

http://www.sdutacm.org/sdutoj/problem.php?action=showproblem&problemid=3252

Lowest Unique Price

Time Limit: 1000ms   Memory limit:65536K  

题目描述

  Recently mybuddies and I came across an idea! We want to build a website to sell things ina new way.
  For each product, everyone could bid at a price, orcancel his previous bid, finally we sale the product to the one who offered the
"lowest unique price". The lowest unique price is defined to be thelowest price that was called only once.
  So we need aprogram to find the "lowest unique price", We'd like to write aprogram to process the customers' bids and answer the 
  query of what's thecurrent lowest unique price.
  All what we neednow is merely a programmer. We will give you an "Accepted" as long asyou help us to write the program.

输入

  The first line ofinput contains an integer T, indicating the number of test cases (T ≤ 60).
  Each test case begins with a integer N (1 ≤ N ≤ 200000)indicating the number of operations.
  Next N lines each represents an operation.
  There are three kinds of operations:
  "b x": x(1 ≤ x ≤ 106) is an integer, this means a customer bids at price x.
  "c x": acustomer has canceled his bid at price x.
  "q" :means "Query". You should print the current lowest unique price.
  Our customers arehonest, they won\'t cancel the price they didn't bid at.

输出

  Please print the current lowest unique price forevery query ("q"). Print "none" (without quotes) if thereis no lowest unique price.

示例输入

2
3
b 2
b 2
q
12
b 2
b 2
b 3
b 3
q
b 4
q
c 4
c 3
q
c 2
q

示例输出

none
none
4
3
2

提示

   这个题的大意是,有很多顾客投标和取消投标,每次查询给出不重复的投标的最小值。
   比如投标有(1,1,2,2,3,4,4,5),那么查询之后就显示3,如果进行取消比如取消一个2,那么投标有(1,1,2,3,4,4,5),那么查询之后
   就是2,如果再增加2,3,5那么就没有不重复的最小值,那么就显示”none”.这样我们想到利用STL里面的priority_queue进行一定的修改。

代码

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
const int maxx(1e6+10);/****所有可能出现的投标值得最大值***/
int now[maxx];/***标记某个值在pq这个优先队列中的个数***/
int _minus[maxx];/***标记某个在pq这个优先队列中,还要取消的次数***/
priority_queue <int > pq;
priority_queue <int > tmp;
void init()/***仅作初始化***/
{
    memset(now,0,sizeof(now));
    memset(_minus,0,sizeof(_minus));
    while(!pq.empty())
        pq.pop();
    while(!tmp.empty())
        tmp.pop();
}
void query()
{
    int _now;
    while(!pq.empty())
    {
        _now=pq.top();
        if(_minus[-_now]>0)/****如果还有要进行取消,那么就把他弹出去,并且这一定不是求的点****/
        {
            now[-_now]--;
            _minus[-_now]--;
            pq.pop();
        }
        else
        {
            if(now[_now]==1)/****如果在队列中只有一个,并且不需要取消,那么这必然是要求的点****/
            {
                cout<<-_now<<endl;
                break;
            }
            else
            {
                tmp.push(_now);/****此时证明要求的点如果存在的话,应该在当前值的后面,把当前值弹出,
                然后存在tmp这个优先队列中****/
                pq.pop();
            }
        }
    }
    if(pq.empty())/***如果已经弹空了还是没有找到,则证明不存在***/
    {
        puts("none");
    }
    while(!tmp.empty())/****把存在优先队列里的节点全部弹回pq这个优先队列******/
    {
        _now=tmp.top();
        tmp.pop();
        pq.push(_now);
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    char cmd;
    int a;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        init();
        while(n--)
        {
            scanf(" %c",&cmd);
            switch(cmd)
            {
            case 'b':/****投标时,把这个数放入优先队列pq,在优先队列pq中的个数++****/
                scanf("%d",&a);
                now[a]++;
                pq.push(-a);/****因为优先队列是从大到小排的,每次摘出来的都是最大的,因此我们取一个相反数****/
                break;
            case 'c':
                scanf("%d",&a);
                _minus[a]++;/****记录要取消还没有取消的次数****/
                break;
            default :
                query();
                break;
            }
        }
    }
    return 0;
}
/************************************** 
 Problem id    : SDUT OJ 3252  
 User name     : crawl  
  Result       : Accepted  
  Take Memory  : 8540K  
  Take Time    : 720MS  
  Submit Time  : 2016-05-26 20:13:46  
**************************************/  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值