题意:一个人想邀请n个人出去玩,假设当前同意和他一起去的人数为cnt,那么他去邀请i的时候,i同意的条件是L[i]<=cnt<=R[i],L[i],R[i]是给定的,问怎样安排邀请顺序,使得有最多的人同意
思路:由于同意他的条件是cnt,不妨在当前状态下将所有没被邀请的人分成3类,一种是R[i]<cnt的,一种是L[i]<=cnt<=R[i]的,一种是L[i]>cnt的,对于第一种已经不可能同意了,因为cnt是递增的,对于第三种现在根本不用考虑,而对于第二种,那么都可以被邀请,且被邀请了一定会同意。明显应该邀请R[i]最小的,因为他们总是比其他人最先变成第一种人。于是得到一个贪心算法,每次选择L[i]<=cnt的所有没邀请的人中R[i]最小的。而这可以每次在cnt发生变化时,用set来维护第二种人的集合,并可以在logn的时间内找到R[i]最小的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #include <map>#include <set>#include <cmath>#include <ctime>#include <deque>#include <queue>#include <stack>#include <vector>#include <cstdio>#include <string>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define X first#define Y second#define pb push_back#define mp make_pair#define all(a) (a).begin(), (a).end()#define fillchar(a, x) memset(a, x, sizeof(a))typedef long long ll;typedef pair<int, int> pii;typedef unsigned long long ull;#ifndef ONLINE_JUDGEvoid RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>void print(const T t){cout<<t<<endl;}template<typename F,typename...R>void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}#endiftemplate<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}template<typename T>void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}template<typename T>void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}const double PI = acos(-1.0);const int INF = 1e9 + 7;/* -------------------------------------------------------------------------------- */const int maxn = 1e5 + 7;const int M = 1e9;struct Node { int L, R, id; bool operator < (const Node &that) const { return R < that.R; } Node(int L, int R, int id): L(L), R(R), id(id) {} Node() {}};multiset<Node> S;int L[maxn], R[maxn];pii node[maxn];vector<int> G[maxn];int main() {#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout);#endif // ONLINE_JUDGE int T; cin >> T; while (T --) { int n; cin >> n; S.clear(); for (int i = 0; i <= n; i ++) { G[i].clear(); } for (int i = 0; i < n; i ++) { scanf("%d", L + i); G[L[i]].pb(i); } for (int i = 0; i < n; i ++) { scanf("%d", R + i); node[i] = mp(L[i], R[i]); } for (int i = 0; i < G[0].size(); i ++) { int id = G[0][i]; S.insert(Node(node[id].X, node[id].Y, id)); } vector<int> ans; vector<bool> vis(n); int cnt = 0; while (1) { multiset<Node>::iterator iter = S.lower_bound(Node(0, cnt, 0)); if (iter == S.end()) break; ans.pb((*iter).id); vis[(*iter).id] = true; S.erase(iter); cnt ++; for (int i = 0; i < G[cnt].size(); i ++) { int id = G[cnt][i]; S.insert(Node(node[id].X, node[id].Y, id)); } } for (int i = 0; i < n; i ++) { if (!vis[i]) ans.pb(i); } printf("%d
", cnt); for (int i = 0; i < n; i ++) { printf("%d%c", ans[i] + 1, i == n - 1? '
' : ' '); } } return 0;} |