题目链接:传送门
题意:
邀请n个人去参加聚会,对于第i个人只有当去人数大于等于li,小于等于ri的时候这个人才会去参加聚会,
让你确定一个邀请的顺序,使得最后去参加聚会的人数最多。
分析:
读完题目后就感觉这个题是个贪心,但是没有想好怎么去维护,比赛完了看完题解感觉太水了。。。
首先肯定是要按照l对所有的数进行排序,比如说我们当前已经有tot个人确定参加了,那么剩下的我们
还要贪心的进行选择。选择满足l<=tot&&r>=tot中的r最小的那个人,很明显,只有这样选择对后来人的
影响才是最小的。对整体才是最优的。
用优先队列维护的代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <set>
#include <vector>
using namespace std;
const int maxn = 1e5+10;
struct nod{
int l,r,id;
bool operator < (const struct nod & tmp)const{
return r > tmp.r;
}
}p[maxn];
int ans[maxn];
bool vis[maxn];
bool cmp(const struct nod &p1,const struct nod &p2){
if(p1.l==p2.l) return p1.r<p2.r;
return p1.l<p2.l;
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&p[i].l);
p[i].id=i;
}
for(int i=1;i<=n;i++){
scanf("%d",&p[i].r);
}
sort(p+1,p+n+1,cmp);
int tot=0,i=1,id=0;
priority_queue<nod>Q;
while(1){
while(p[i].l<=tot&&i<=n) Q.push(p[i]),i++;
while(!Q.empty()){
nod tmp = Q.top();
if(tmp.r>=tot) break;
ans[++id]=tmp.id;
Q.pop();
}
if(Q.empty()) break;
else{
ans[++id] = Q.top().id;
tot++;
Q.pop();
}
}
while(i<=n) ans[i]=p[i].id,i++;
printf("%d\n",tot);
for(int i=1;i<n;i++) printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
return 0;
}
用set维护的代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <set>
using namespace std;
const int maxn = 1e5+10;
struct nod {
int l ,r ,id ;
bool operator < (const struct nod &tmp) const {
if(l == tmp.l)
return r < tmp.r ;
return l<tmp.l ;
}
} p[maxn];
int ans[maxn];
bool vis[maxn];
set<pair<int,int > >st;
set<pair<int,int > >::iterator it;
int main() {
int t,n;
scanf("%d",&t);
memset(vis,0,sizeof(vis));
while(t--) {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%d",&p[i].l);
p[i].id=i;
}
for(int i=1; i<=n; i++) {
scanf("%d",&p[i].r);
}
sort(p+1,p+1+n);
//memset(vis,0,sizeof(vis));
int tot=0,i=1;
st.clear();
while(true) {
while(tot>=p[i].l&&i<=n) st.insert(make_pair(p[i].r,p[i].id)),i++;
if(st.size()==0) break;
while(st.size()) {
it = st.begin();
if(it->first >= tot) break;
st.erase(st.begin());
}
if(st.size()) {
it = st.begin();
ans[++tot] = it->second;
vis[it->second]=1;
st.erase(st.begin());
}
}
printf("%d\n",tot);
for(int i=1; i<=n; i++) {
if(!vis[i]) ans[++tot]=i;
else vis[i]=0;
}
for(int i=1; i<n; i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
return 0;
}