CF749D Leaving Auction

题目链接:

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

题目大意:

一场拍卖会,共n个买家。这些买家共出价n次,有的买家可能一次都没有出价。每次出价用(ai,bi)表示,ai为此次出价人的编号,bi为价格。出价严格递增(bi<bi+1)并且没有玩家在一轮竞拍中在没有其他竞争对手的情况下自动增加自己的出价(ai!=ai+1)。现在给定q次查询,每次去掉一些出价者及其所有出价,问最后谁是赢家并且他以什么价格赢得拍卖品。

解题思路:

首先预处理所有的出价,保存每个买家的出价序列,最高出价和最低出价。然后维护一个set。其中保存出价者id和他的出价序列中的最高出价maxn,整个set按照maxn从大到小的顺序排序。对于每次查询,从set中删掉出局的人,如果此时set大小为0,输出“0 0”;大小为1,则只有一个买家,他赢得了拍卖品且价格为他的所有出价中的最小值;否则找maxn最高的人和第二高的人。最终的价格应该是在maxn最高的人的出价序列中比maxn第二高的人的最高出价高一点点的值。考虑到是有序的,二分即可。之后不要忘了把之前剔除掉的人再insert回来。

开始时我在set的每个节点中保存了相应买家的出价序列,结果T了很多次,真是被自己蠢哭了......

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <vector>
  4 #include <set>
  5 #include <algorithm>
  6 #include <cstring>
  7 using namespace std;
  8 const int INF = 0x3f3f3f3f;
  9 vector<int> G[200005];
 10 int n, a, b;
 11 int maxn[200005];
 12 int minn[200005];
 13 int d[200005];
 14 int max(int a, int b)
 15 {
 16     return a > b ? a : b;
 17 }
 18 int min(int a, int b)
 19 {
 20     return a < b ? a : b;
 21 }
 22 struct node
 23 {
 24     int index;
 25     int maxn;
 26 };
 27 struct cmp
 28 {
 29     bool operator ()(const node & a, const node & b)const
 30     {
 31         return a.maxn > b.maxn;
 32     }
 33 };
 34 int main()
 35 {
 36     cin >> n;
 37     memset(minn, 0x3f, sizeof(minn));
 38     for (int i = 0; i < n; i++)
 39     {
 40         scanf("%d %d", &a, &b);
 41         G[a].push_back(b);
 42         maxn[a] = max(maxn[a], b);
 43         minn[a] = min(minn[a], b);
 44     }
 45     set<node, cmp> s;
 46     for (int i = 1; i <= n; i++)
 47     {
 48         if (G[i].size())
 49         {
 50             node tmp;
 51             tmp.index = i;
 52             tmp.maxn = maxn[i];
 53             s.insert(tmp);
 54         }
 55     }
 56     int T, x;
 57     cin >> T;
 58     for (int i = 0; i < T; i++)
 59     {
 60         scanf("%d", &x);
 61         for (int j = 0; j < x; j++)
 62         {
 63             scanf("%d", &d[j]);
 64             node t;
 65             t.index = d[j];
 66             t.maxn = maxn[d[j]];
 67             s.erase(t);
 68         }
 69         if (s.size() == 0)
 70         {
 71             puts("0 0");
 72         }
 73         else if (s.size() == 1)
 74         {
 75             printf("%d %d\n", s.begin()->index, minn[s.begin()->index]);
 76         }
 77         else
 78         {
 79             set<node, cmp>::iterator t = s.begin();
 80             node y;
 81             y.index = t->index;
 82             y.maxn = t->maxn;
 83             s.erase(s.begin());
 84             set<node, cmp>::iterator t2 = s.begin();
 85             vector<int>::iterator it;
 86             it = upper_bound(G[t->index].begin(), G[t->index].end(), t2->maxn);
 87             if (it != G[t->index].end())
 88             {
 89                 printf("%d %d\n", y.index, *it);
 90             }
 91             else
 92             {
 93                 puts("0 0");
 94             }
 95             s.insert(y);
 96         }
 97         for (int j = 0; j < x; j++)
 98         {
 99             node t;
100             t.index = d[j];
101             t.maxn = maxn[d[j]];
102             if (G[t.index].size())
103                 s.insert(t);
104         }
105     }
106     return 0;
107 }

 

转载于:https://www.cnblogs.com/wangyiming/p/6216285.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值