Codeforces 749D:Leaving Auction(set+二分)
http://codeforces.com/contest/749/problem/D
题意:有几个人在拍卖场竞价,一共有n次喊价,有q个询问,每一个询问有一个num,接下来num个人从这次拍卖中除去,问对于每一个询问减掉num个人后是谁赢了拍卖,最小的价格是多少。
思路:昨晚不会做。想法好神奇(我太弱)。对于每个人用 set-S 装起来其每次喊价的下标,然后用一个数组order按价格从大到小的顺序将每个人装起来,对于每一个询问,把这num个人丢到一个 set-s 里面,然后在order里面找没出现过在 s 里面的,那么这个人 x 就是这场拍卖的胜者,那么还要考虑他喊的最低价格,将 x 也丢到 s 里面,再找一个 y,这个 y 是第二个大的,所以在 S[x] 里面二分找大于 y 喊过的最大价格就是答案了。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <string> 7 #include <iostream> 8 #include <stack> 9 #include <map> 10 #include <queue> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 #define N 200010 15 #define INF 0x3f3f3f3f 16 bool vis[N]; 17 int v[N][2]; 18 vector<int> order; 19 set<int> S[N]; 20 21 int main() 22 { 23 int n; 24 cin >> n; 25 for(int i = 0; i < n; i++) { 26 scanf("%d%d", &v[i][0], &v[i][1]); 27 S[v[i][0]].insert(i); 28 } 29 for(int i = n - 1; i >= 0; i--) { 30 if(!vis[v[i][0]]) { 31 vis[v[i][0]] = 1; 32 order.push_back(v[i][0]); 33 } 34 } 35 int q; 36 cin >> q; 37 while(q--) { 38 set<int> s; 39 int num; 40 scanf("%d", &num); 41 while(num--) { 42 int k; 43 scanf("%d", &k); 44 s.insert(k); 45 } 46 int x = -1, y = -1; 47 for(int i = 0; i < order.size(); i++) { 48 if(s.find(order[i]) == s.end()) { 49 x = order[i]; 50 break; 51 } 52 } 53 if(x == -1) puts("0 0"); 54 else { 55 s.insert(x); 56 for(int i = 0; i < order.size(); i++) { 57 if(s.find(order[i]) == s.end()) { 58 y = order[i]; 59 break; 60 } 61 } 62 if(y == -1) { 63 printf("%d %d\n", x, v[*S[x].begin()][1]); 64 } else { 65 set<int>::iterator it = S[y].end(); 66 int pos = *(--it); 67 it = S[x].upper_bound(pos); 68 printf("%d %d\n", x, v[*it][1]); 69 } 70 } 71 } 72 return 0; 73 }