传送门:点击打开链接
题目大意:
有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;
}