hdu5360 (贪心+优先队列)
做法是每次选取起始条件符合,并且结束条件最早的。(每个人的起始时间为l,结束时间为r)
#include <iostream> #include <stdio.h> #include <memory.h> #include <queue> #include <vector> using namespace std; int N,T; struct node { int start; int End; int index; bool friend operator<(node n1,node n2) { return n1.End>n2.End; } }; bool vis[1000010]; int cmp(node a,node b) { return a.start < b.start ; } node input[1000010]; vector<node> V[100010]; void slove() { int sum=0; vector<int> ans; priority_queue<node> Q; //初始化 for(int i=0;i<N;i++)//此处应该为i小于n,不用小于等于,因为总人数只有N个时,除去自己,在自己前面接受邀请的最多只有N-1个。 { V[i].clear(); } //vector数组相当于二维的vector,第一维表示它的起始时间,第二维无意义。因为加入队列之后还需要按照结束时间排序。 for(int i=0;i<N;i++) { V[input[i].start].push_back(input[i]); } while(true) { bool flag=false; //选取起始时间刚好符合的元素加入队列。 for(int i=0;i<V[sum].size();i++) { Q.push(V[sum][i]); } //选取一个未被访问并且结束时间最小但结束时间又大于sum(也是就是当前已经邀请到的人数)的元素 while(!Q.empty()) { if(Q.top().End>=sum&&!vis[Q.top().index]) { vis[Q.top().index]=true; ans.push_back(Q.top().index); sum++; Q.pop(); flag=true; break; } //如果没有break出去就说明没有进if语句内部,所以需要pop出去 Q.pop(); } //如果没找到说明当前sum已经大于剩下未被选取的元素的起始时间了,所以筛选工作已经完成 if(!flag) break; } cout<<sum<<endl; if(sum) { printf("%d",ans[0]); for(int i=1;i<ans.size();i++) printf(" %d",ans[i]); for(int i=1;i<=N;i++) if(!vis[i]) printf(" %d",i); cout<<endl; } else { printf("1"); for(int i=2;i<=N;i++) if(!vis[i]) printf(" %d",i); cout<<endl; } } int main() { scanf("%d",&T); //输入 while(T--) { memset(vis,0,sizeof(vis)); scanf("%d",&N); for(int i=0;i<N;i++) { scanf("%d",&input[i].start); input[i].index=i+1; } for(int i=0;i<N;i++) { scanf("%d",&input[i].End); } slove(); } return 0; }