题意:有有许多人参加拍卖,问当假定某些人不参加的时候剩余的人当中谁是最终的赢家,输出他的编号和最终竞价,注:每个人都不能和自己竞价,即若某人连续竞价两次,以第一次价格为准。输入数据保证竞价递增。
思路:
我们只要把每个人竞价的最大值存起来, 并且把每个人的所有竞价维护在一个有序数组(方便二分), 对于一组询问, 我们从大到小遍历这k个数,把不在这k个数的最终竞价最大的两个人找到(复杂度O(K)), 然后在竞价最大的那个人的set里二分第二大的人的竞价最大值就行了。
不能写:it=ts.end()--;
得写:
it=ts.end();
it--;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<vector>
#include<queue>
using namespace std;
int n;
struct node
{
int id;
int num=0;
friend bool operator<(node a,node b)
{
return a.num<b.num;
}
}itm[200005];
set<int>s[200005];
set<node>ts;
int dc[200005];
int vis[200005];
int main()
{
while(~scanf("%d",&n))
{
for(int i=0;i<=200000;i++)
s[i].clear();
ts.clear();
int maxid=0;
for(int i=1;i<=n;i++)
{
int id,num;
scanf("%d%d",&id,&num);
itm[id].id=id;
itm[id].num=num;
maxid=max(maxid,id);
s[id].insert(num);
}
for(int i=1;i<=maxid;i++)
{
ts.insert(itm[i]);
}
int q;
scanf("%d",&q);
while(q--)
{
int m;
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d",&dc[i]);
vis[dc[i]]=1;
}
int ans1=-1,ans2=-1;
set<node>::iterator it;
set<int>::iterator it1;
it=ts.end();
it--;
while(1)
{
int tid=it->id;
//cout<<"tid:"<<tid<<":"<<it->num<<endl;
if(vis[tid]==0)
{
if(ans1==-1)
{
ans1=tid;
}
else if(ans2==-1 && tid!=ans1)
{
ans2=tid;
break;
}
}
if(it==ts.begin())
{
break;
}
it--;
}
//cout<<ans1<<" : "<<ans2<<endl;
if(ans1==-1 && ans2==-1)
{
printf("0 0\n");
}
else if(ans2==-1)
{
it1=s[ans1].begin();
printf("%d %d\n",ans1,*it1);
}
else
{
it1=s[ans1].upper_bound(itm[ans2].num);
printf("%d %d\n",ans1,*it1);
}
for(int i=0;i<m;i++)
{
vis[dc[i]]=0;
}
}
}
}