CodeForces 749D Leaving Auction

时间:2022-01-17 23:08:14

二分查找,$set$。

对于某一次询问,如果把人删光了,那么输出$0$ $0$。

如果只剩下$1$个人,那么输出那个人喊的最低价格。

如果剩下的人数有大于等于两个,

CodeForces 749D Leaving Auction

这时最底下出现的情景必然是红色部分由一个人喊,紫色部分由另一个人喊。

这两个人分别是喊价最高价次高者和最高者,并且红色部分最后一个位置的下一个位置就是答案。因此只需在获取两个人的信息后,在最高者喊价序列中二分即可。

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<iostream>
#include<set>
using namespace std; const int maxn=;
int n,q; struct X
{
int id,val;
}s[maxn]; struct XX{
int a,b;
XX () { }
XX(int A,int B)
{
a=A;
b=B;
} bool operator < (const XX &aa) const
{
return b>aa.b;
}
}; XX fir,sec; vector<int> v[maxn];
set<XX> h; int tmp[maxn],mn[maxn],mx[maxn]; bool check(int x)
{
int tt=v[fir.a][x];
if(s[tt].val<sec.b) return ;
return ;
} int main()
{
scanf("%d",&n);
for(int i=;i<=;i++) mx[i]=,mn[i]=; for(int i=;i<=n;i++)
{
scanf("%d%d",&s[i].id,&s[i].val);
v[s[i].id].push_back(i);
mx[s[i].id]=max(mx[s[i].id],s[i].val);
mn[s[i].id]=min(mn[s[i].id],s[i].val);
} for(int i=;i<=;i++)
{
if(mx[i]==) continue;
h.insert(XX(i,mx[i]));
} scanf("%d",&q);
for(int i=;i<=q;i++)
{
int k; scanf("%d",&k);
for(int j=;j<=k;j++) scanf("%d",&tmp[j]);
for(int j=;j<=k;j++)
{
if(mx[tmp[j]]==) continue;
h.erase(XX(tmp[j],mx[tmp[j]]));
} if(h.size()==)
{
printf("0 0\n");
}
else if(h.size()==)
{
XX ans = *h.begin();
printf("%d %d\n",ans.a,mn[ans.a]);
}
else
{
set<XX>::iterator iter;
int cnt=; for(iter = h.begin() ; iter != h.end(); iter++)
{
cnt++;
if(cnt==) fir = *iter;
else if(cnt==) { sec = *iter; break; }
} int L=,R=v[fir.a].size()-;
int ans; while(L<=R)
{
int mid=(L+R)/;
if(check(mid)) ans=mid,R=mid-;
else L=mid+;
} int tt=v[fir.a][ans];
printf("%d %d\n",s[tt].id,s[tt].val); } for(int j=;j<=k;j++)
{
if(mx[tmp[j]]==) continue;
h.insert(XX(tmp[j],mx[tmp[j]]));
}
}
return ;
}