贪心的思路还是比较好想的,每次选择cur(已经邀请成功的人数)所在的区间中右端点最小的(因为右端点大的在后面可以邀请成功的几率大),然后很自然的想到可以用一个优先队列来维护这些区间,只要每次把左端点小于等于cur的区间放到优先队列中即可。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <vector> 5 #include <queue> 6 using namespace std; 7 8 const int N = 100001; 9 bool visit[N]; 10 int a[N]; 11 12 struct Node 13 { 14 int r, id; 15 Node(){} 16 Node( int _r, int _id ) 17 { 18 r = _r, id = _id; 19 } 20 bool operator < ( const Node & o ) const 21 { 22 return r > o.r; 23 } 24 }; 25 26 vector<Node> v[N]; 27 priority_queue<Node> q; 28 29 int main () 30 { 31 int t; 32 scanf("%d", &t); 33 while ( t-- ) 34 { 35 int n; 36 scanf("%d", &n); 37 for ( int i = 0; i <= n; i++ ) 38 { 39 v[i].clear(); 40 } 41 for ( int i = 1; i <= n; i++ ) 42 { 43 scanf("%d", a + i); 44 } 45 for ( int i = 1; i <= n; i++ ) 46 { 47 int tmp; 48 scanf("%d", &tmp); 49 v[a[i]].push_back( Node( tmp, i ) ); 50 } 51 memset( visit, 0, sizeof(visit) ); 52 int cur = 0, cnt = 1; 53 while ( 1 ) 54 { 55 for ( int i = 0; i < v[cur].size(); i++ ) 56 { 57 q.push(v[cur][i]); 58 } 59 bool flag = false; 60 while ( !q.empty() ) 61 { 62 Node tt = q.top(); 63 q.pop(); 64 a[cnt++] = tt.id; 65 visit[tt.id] = true; 66 if ( tt.r >= cur ) 67 { 68 cur++; 69 flag = true; 70 break; 71 } 72 } 73 if ( !flag ) 74 { 75 break; 76 } 77 } 78 for ( int i = 1; i <= n; i++ ) 79 { 80 if ( !visit[i] ) 81 { 82 a[cnt++] = i; 83 } 84 } 85 printf("%d ", cur); 86 for ( int i = 1; i < n; i++ ) 87 { 88 printf("%d ", a[i]); 89 } 90 printf("%d ", a[n]); 91 } 92 return 0; 93 }