Lowest Unique Price(最小且唯一价格---2015山东省省赛B题解题报告)

Description
Recently my buddies and I came across an idea! We want to build a website to sell things in a new way.
For each product, everyone could bid at a price, or cancel 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 the lowest price that was called only once.
So we need a program to find the “lowest unique price”, We’d like to write a program to process the customers’ bids and answer the query of what’s the current lowest unique price.
All what we need now is merely a programmer. We will give you an “Accepted” as long as you help us to write the program.
Input
The first line of input 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”: a customer has canceled his bid at price x.
“q” : means “Query”. You should print the current lowest unique price.
Our customers are honest, they won’t cancel the price they didn’t bid at.
Output
Please print the current lowest unique price for every query (“q”). Print “none” (without quotes) if there is no lowest unique price.
Sample Input
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
Sample Output
none
none
4
3
2
题意:
依次出价,随时可能撤销出价,随时可能询问当前最低且为唯一的价格
b:添加元素,c:删除指定元素(若有多个相同元素只删除一个),q:询问当前最小且唯一的元素
思路:
利用映射记录当前元素出现的次数(b:就增加一次,c:就减少一次),当出现次数为一时就将此元素丢进Set,否则将该元素擦除。最后询问时利用set的有序性输出set的第一个元素即可。
ps:常规利用数组存会超时
Code:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll long long
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("in.txt", "r", stdin);
#define Write() freopen("out.txt", "w", stdout);


#define M 137
#define N 55

using namespace std;


const int inf = 0x7f7f7f7f;
const int mod = 1000000007;

int main()
{
    //Read();
   set<int> Set;
   set<int>::iterator it;
   map<int,int> Map;
   int n;
   scanf("%d",&n);
   while(n--)
   {
       Read();
       int m;
       Set.clear();
       Map.clear();
       scanf("%d",&m);
       while(m--)
       {
           char c[3];
           scanf("%s",c);
           if(c[0]=='b')
           {
             int x;
             scanf("%d",&x);
             Map[x]++;
             if(Map[x]==1)
             {
                 Set.insert(x);
             }
             else if(Map[x]>1)
             {
                 Set.erase(x);
             }
           }
           if(c[0]=='q')
           {
               if(Set.empty())
                printf("none\n");
               else
               {
                   it=Set.begin();
                   printf("%d\n",*it);
               }
           }
           if(c[0]=='c')
           {
               int x;
               scanf("%d",&x);
               Map[x]--;
               if(Map[x]==1)
               {
                   Set.insert(x);
               }
               else
               {
                   Set.erase(x);
               }

           }
       }
   }


   return 0;
}

其它:
关于iterator:
iterator是C++标准库(STL)中的迭代器
比如你建一个链表
(要记得 include list include iostream

list<char> A;

list<char>::iterator it,这样,就可以对链表进行遍历了~
其实,你可以把它理解成类似指针的东西~当然,只是用处差不多,使用方式和声明方式可是完全不同的
PS:一个简单的小程序段,可以说明iterator的用处~

#include <list>
#include <iostream>
using namespace std;
void main(void)
{
    int a[]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    list<int> name(a,a+10);
    list<int>::iterator it;
    for (it = name.begin(); it != name.end(); it++)
    {
        cout << *it << endl;
    }
}

关于键盘缓存区什么的真是搞不懂,比如下面这段代码注释掉getchar()后无论是用回车间隔还是空格间隔都不能正常读入:

char a[5];
    for (int i=0;i<5;i++)
    {
        scanf("%c",&a[i]);
        //getchar();
    }
    for(int i=0;i<5;i++)
    {
        printf("%c\n",a[i]);
    }

然后改成这样后不用插getchar,无论是用回车间隔还是空格间隔也可以正常读入了:
先读%s,再赋第一个元素达到取得第一个字母的目的

char a[5];
    char b[5];
    for (int i=0;i<5;i++)
    {
        scanf("%s",b);
        a[i]=b[0];
    }
    for(int i=0;i<5;i++)
    {
        printf("%c\n",a[i]);
    }

平常总是会在插入getchar时弄错,本题读入bcq时用scanf %c总是不好插getchar,所以干脆用scanf %s再c[0]取得第一个字母好了。
那么本题也可以这么改咯:

 char a[3],c;
 scanf("%s",a);
 c=a[0];  //不用getchar,取得了第一个字母

参考链接:
http://blog.csdn.net/hy1405430407/article/details/45787951
http://zhidao.baidu.com/link?url=RPywXZR6O1OftQlui-QWIXWCIvHGZKE4G6h4rp_AVkk2hD428t0ZlFtWUq1-b8NzcK1E-onKvfQ8ccLgeK9vHa

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值