题意:拍卖一件物品,有n个竞标,一个人可以有多个竞标。给出n个竞标,a[i],b[i].a[i]表示人的序号,b[i]表示竞标价格。
接下来有q个询问,每次一个k,之后k个数表示该序号的人缺席。问谁最终以多少钱得标。如果没有输出0 0,否则输出序号和价钱。
思路:可以按竞标价格排个序,先将所有人逆序加入set集合中,由于set会自动排序,所以set中存2个元素,
一个用来防止其加入自动排序,一个存每个人的编号。然后再将未出席的删除,如果最后set中没有人了,
则输出0 0,如果还剩1个,则输出该人的最小出价,否则的话,输出set中第一个人所有出价中第一次大于
set中第2个人的最大出价的出价,可以用二分查找。 set删除一个数的时间复杂度为O(logn),vector为O(n),
#include<iostream> #include<algorithm> #include<string> #include<cstring> #include<cstdio> #include<queue> #include<map> #include<vector> #include<set> using namespace std; vector<int>mp[200005]; set<pair<int,int> >aa; int a[200005],v[200005],b[200005]; int fun(int x,int y) { int k=mp[y].size(); int m=mp[y][k-1]; int r=mp[x].size()-1; int l=0; while(l<r) { int mid=(l+r)/2; if(mp[x][mid]<=m) l=mid+1; else r=mid; } return mp[x][r]; } int main() { int n,s,w; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d %d",&s,&w); a[i]=s; mp[s].push_back(w); } for(int i=n;i>=1;i--) { if(!v[a[i]]) { aa.insert(make_pair(-i,a[i])); v[a[i]]=i; } } set<pair<int,int> >::iterator it; int t; scanf("%d",&t); while(t--) { int k; scanf("%d",&k); for(int i=1;i<=k;i++) { scanf("%d",&w); b[i]=w; if(v[w]==0) continue; aa.erase(make_pair(-v[w],w)); } if(aa.size()==0) printf("0 0 "); else if(aa.size()==1) { int x=aa.begin()->second; printf("%d %d ",x,mp[x][0]); } else { int x=aa.begin()->second; int y=(++aa.begin())->second; printf("%d %d ",x,fun(x,y)); } for(int i=1;i<=k;i++) { if(v[b[i]]) aa.insert(make_pair(-v[b[i]],b[i])); } } return 0; }
所以这题用vector会时间超限。