CodeForces 749D Leaving Auction
二分查找,$set$。
对于某一次询问,如果把人删光了,那么输出$0$ $0$。
如果只剩下$1$个人,那么输出那个人喊的最低价格。
如果剩下的人数有大于等于两个,
这时最底下出现的情景必然是红色部分由一个人喊,紫色部分由另一个人喊。
这两个人分别是喊价最高价次高者和最高者,并且红色部分最后一个位置的下一个位置就是答案。因此只需在获取两个人的信息后,在最高者喊价序列中二分即可。
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<iostream> #include<set> using namespace std; const int maxn=200010; 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 0; return 1; } int main() { scanf("%d",&n); for(int i=1;i<=200000;i++) mx[i]=0,mn[i]=2000000000; for(int i=1;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=1;i<=200000;i++) { if(mx[i]==0) continue; h.insert(XX(i,mx[i])); } scanf("%d",&q); for(int i=1;i<=q;i++) { int k; scanf("%d",&k); for(int j=1;j<=k;j++) scanf("%d",&tmp[j]); for(int j=1;j<=k;j++) { if(mx[tmp[j]]==0) continue; h.erase(XX(tmp[j],mx[tmp[j]])); } if(h.size()==0) { printf("0 0\n"); } else if(h.size()==1) { XX ans = *h.begin(); printf("%d %d\n",ans.a,mn[ans.a]); } else { set<XX>::iterator iter; int cnt=0; for(iter = h.begin() ; iter != h.end(); iter++) { cnt++; if(cnt==1) fir = *iter; else if(cnt==2) { sec = *iter; break; } } int L=0,R=v[fir.a].size()-1; int ans; while(L<=R) { int mid=(L+R)/2; if(check(mid)) ans=mid,R=mid-1; else L=mid+1; } int tt=v[fir.a][ans]; printf("%d %d\n",s[tt].id,s[tt].val); } for(int j=1;j<=k;j++) { if(mx[tmp[j]]==0) continue; h.insert(XX(tmp[j],mx[tmp[j]])); } } return 0; }