Codeforces Round #388 (Div. 2)D. Leaving Auction

传送门:点击打开链接

题目大意:

有n<=200000个人参加拍卖一件商品,总共出价n次,但是并不保证一人出价一次,有可能有人没有机会出价。

每一次出价都是一个整数对(a[i],b[i])(a[i]<=n,b[i]<=1e9),a[i]表示出价的人的编号以及b[i]是出价的价格。保证b[i]<b[i+1]对i<n成立以及a[i]!=a[i+1]
有q<=2e5个询问
每一个询问包含一个整数k以及k个人的编号l[j],保证k的总和不会超过2e5
问如果这些人不出现的话,谁会获得这件商品?

对于每一个询问,输出两个整数,胜出者的编号以及胜出者出的价格,如果没有人胜出,输出两个0


分析:数据结构的题。对于每个人出的价格都用vector加进去,用map以第一键值保存人的编号,第二键值保存该人的最大出价。读完n次出价数据后,用另一个map以第一键值保存最大出价,第二键值保存该人的编号。对于q次询问,先把k个编号中出价过的人从第二个map中删去,此时该map中第一键值最大的人就是胜出者,可以通过出价第二高的人的出价来用upper_bound查询以胜出者为下标的vector中最少需要出的价格。每次输出答案后把删掉的人加上去即可。

两个map的作用还是挺大的,尤其是第二个以第一键值保存最大出价的map,如果不用它就需要直接遍历每个人*vector.end()--,也就是每个人的出价最大值,这样会T。


其实这题就是个STL的搞脑子题。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 200005;
vector<int> v[maxn];
bool fir[maxn];
int a[maxn];
int main()
{
    int n, m, k, peo, pri;
    while(cin >> n)
    {
        memset(fir, false, sizeof(fir));
        set<int> st;
        map<int, int> mp, p;
        for(int i = 0; i < n; i++)
        {
            cin >> peo >> pri;
            if(!fir[peo])
            {
                if(!v[peo].empty())
                    v[peo].clear();
                fir[peo] = true;
                v[peo].clear();
                v[peo].push_back(pri);
            }
            else
                v[peo].push_back(pri);
            mp[peo] = max(mp[peo], pri);
        }
        for(map<int, int> ::iterator iter = mp.begin(); iter != mp.end(); iter++)
            p[iter->second] = iter->first;
        cin >> m;
        int index, ans;
        map<int, int> ::iterator iter;
        while(m--)
        {
            cin >> k;
            for(int i = 0; i < k; i++)
            {
                cin >> a[i];
                if(mp[a[i]])
                    p.erase(mp[a[i]]);
            }
            int cnt = p.size();
            if(cnt == 0)
                cout << 0 << " " << 0 << endl;
            else if(cnt == 1)
            {
                iter = p.end();
                iter--;
                index = iter->second;
                ans = *v[index].begin();
                cout << index << " " << ans << endl;
            }
            else
            {
                iter = p.end();
                iter--;
                index = iter->second;
                iter--;
                ans = iter->first;
                ans = *upper_bound(v[index].begin(), v[index].end(), ans);
                cout << index << " " << ans << endl;
            }
            for(int i = 0; i < k; i++)
            {
                if(mp[a[i]])
                    p.insert(make_pair(mp[a[i]], a[i]));
            }
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值