HDOJ 5360 Hiking 【priority_queue】
題目就是說有n個人,
每個人有自己的編號以及自己在被邀請時可以接受的當前的人數範圍[l, r]
要求確定一個邀請序列,使得同意加入隊列的人數最多
標記一個cnt計數當前已經同意邀請的人數,
然後把所有人的數組按照l從小到大排序,
當l ≤ cnt 時表示此人有可能同意邀請,加入優先隊列
對於所有優先隊列裏的人按照r從小到大排序
當r ≥ cnt 是表示此人可以同意邀請,
並且按照最優策略,應該就是r ≥ cnt 並且最接近cnt的那個人此時被邀請
所以將優先隊列中不符合要求的人直接丟出(因爲加入隊列且不符合要求的人在下一個情況中也不可能符合要求了)
然後將符合要求的隊列第一項加入結果集即可
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define clr(c) memset(c, 0, sizeof(c));
#define pi acos(-1.0)
const int INF = 0x3f3f3f3f;
typedef long long ll;
typedef struct soda{
int l, r;
int i; // i-th
bool operator < (const soda& s) const{
return l < s.l;
}
bool operator > (const soda& s) const { return s < *this; }
}s;
struct cmp{ // 最小值優先
bool operator ()(s &s1,s &s2){
return s1.r>s2.r; // 若return值爲true, 就交換s1 s2的位置
}
};
const int MAXL = 1e5+5;
s soda[MAXL];
bool vis[MAXL];
int order[MAXL];
int T, n;
int cnt;
int start;
int leftstart;
priority_queue<s, vector<s>, cmp> q;
void Resolve(){
clr(vis); // clear
clr(order); // clear
while(!q.empty()) q.pop(); // clear
sort(soda+1, soda+1+n);
cnt = 0;
start = 1;
//for(int i = 1; i <= n; i++) printf("%d %d, %d\n", soda[i].l, soda[i].r, soda[i].i);
for(int i = 1; i <= n; i++){
for( ; start <= n && soda[start].l <= cnt; start++){ // l符合要求的進隊
q.push(soda[start]);
}
while(!q.empty() && q.top().r < cnt){ // r不符合要求的丟出去
q.pop();
}
if(!q.empty()){
//printf("q.top().i %d\n", q.top().i);
order[cnt++] = q.top().i;
vis[q.top().i] = true;
q.pop();
}
}
leftstart = cnt;
for(int i = 1; i <= n; i++){
if(vis[i] == false){
order[leftstart++] = i;
}
}
//OUTPUT
printf("%d\n", cnt);
for(int i = 0; i < n; i++){
printf("%d", order[i]);
if(i != n-1) printf(" ");
}
printf("\n");
}
int main(){
scanf("%d", &T);
while(T--){
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &soda[i].l);
for(int i = 1; i <= n; i++) scanf("%d", &soda[i].r);
for(int i = 1; i <= n; i++) soda[i].i = i;
Resolve();
}
return 0;
}