传送门:http://codeforces.com/contest/749/problem/D
题意:有几个人在拍卖场竞价,一共有n次喊价,有q个询问,每一个询问有一个num,接下来num个人从这次拍卖中除去,问对于每一个询问减掉num个人后是谁赢了拍卖,最小的价格是多少。
思路:用set<pair<int, int> >pos维护竞价人的下标和最大值,把最大值作为pair里面的第一关键字(因为set自带排序功能),vector<int>lst[N]维护每个竞价人的所有竞价(从小到大)
每次询问,先从pos中删去k个,这个时候有三种情况
1)pos为空,输出0 0
2)pos有一个,输出这唯一一个竞价人的最低报价
3)pos个数大于等于2,找出pos里面第一大竞价人和第二大竞价人,然后在第一大竞价人里找刚好大于第二大竞价人的最大竞价值的值就可以了
可以参考官方题解:http://codeforces.com/blog/entry/49186
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
vector<int>lst[N];
set<pair<int, int> >pos;
int n, del[N], mx[N];
bool vis[N];
int main(){
scanf("%d", &n);
for(int i=1; i<=n; i++){
int x, y;
scanf("%d%d", &x, &y);
lst[x].push_back(y);
vis[x]=1;
mx[x]=max(mx[x], y);
}
for(int i=1; i<=n; i++)
if(vis[i])pos.insert({mx[i], i});
int q;
scanf("%d", &q);
while(q--){
int k; scanf("%d", &k);
for(int i=1; i<=k; i++){
scanf("%d", &del[i]);
if(vis[del[i]]) pos.erase({mx[del[i]], del[i]});
}
int sz=pos.size();
if(sz==0){
printf("0 0\n");
}
else if(sz==1){
printf("%d %d\n", pos.begin()->second, *lst[pos.begin()->second].begin());
}
else{
auto it1=pos.end(), it2=pos.end(); it1--; it1--; it2--;
int tmpnum=it1->first;
int tmppos=it2->second; //这个地址下的第二个值
auto it=upper_bound(lst[tmppos].begin(), lst[tmppos].end(), tmpnum);
printf("%d %d\n", tmppos, *it);
}
for(int i=1; i<=k; i++)if(vis[del[i]])
pos.insert({mx[del[i]], del[i]});
}
return 0;
}
PS:set不熟练,搞得指针、地址、值乱飞,编译都通不过,调了半天