题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5437
题目大意:Alisha 要举办一个派对,但是他家里的大厅大小有限,所以他一次只能让几个人进来,来的人都会带一份礼物,每个礼物都会有自己的价值。然后进屋子的顺序是以礼物的价值为第一考虑因素,如果礼物价值一样,谁先到就谁先进。
总共有k个人会来,Alisha会开m次门,会询问q次。
当开了m次门之后,如果人还没有进来,那么等到他们全到之后,alisha会再开一次门,让剩下在门外的人全部进到房子里面,进来的先后顺序依旧是原来的那个规则。
#include <stdio.h>
#include <functional>
#include <queue>
#include <algorithm>
using namespace std;
struct node { //优先队列的规则
int val;
int id;
node(int a,int b)
{
val = a;
id = b;
}
bool operator<(const node &b)const
{
if (b.val!=val) //以带的礼物价值先考虑 ,其次考虑先后顺序
{
return b.val>val;
}
return id>b.id;
}
};
struct Peo
{
int time; //来了几个人
int pcount; //要进来几个人
}peo[150010];
bool cmp(const Peo &a,const Peo &b)
{
return a.time<b.time; //来的人数不一定递增,排序一下。
}
char name[150010][210]; //人的名字
int Val[150010]; //带的礼物的价值
int num[150010]; //进去的人的编号
priority_queue <node> qu; //以上面的规则,构造队列
int main()
{
int t,k,m,q;
scanf("%d",&t); //有t组数据
while(t--)
{
scanf("%d%d%d",&k,&m,&q);
for(int i=1;i<=k;i++)
{
scanf("%s%d",name[i],&Val[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&peo[i].time,&peo[i].pcount);
}
sort(peo+1,peo+m+1,cmp);
while (!qu.empty()) //使队列为空
{
qu.pop();
}
int count=1;
int Count=1;
for(int i=1;i<=m;i++)
{
int T=peo[i].time;
while(count<=T) //把来的人直接先存在队列中,出队列的顺序是确定的。
{
qu.push(node(Val[count],count)); //进入队列 并按规则排列
++count; //进入队列的人数增加
}
int X=peo[i].pcount;
for(int j=1;j<=X;j++)
{
if (qu.empty())
{
break;
}
num[Count++]=qu.top().id; //使进去的人的先后编号存入数组中
qu.pop(); //删除队列顶部的数据
}
}
for (int i=count;i<=k;++i) //人全到了之后,剩下没进屋子人之后会进去,所以也需要存起来
{
qu.push(node(Val[i], i));
}
while (!qu.empty())
{
num[Count++] = qu.top().id; //剩下没 进屋子的人也按照规则先后进入,我们把编号存在数组里
qu.pop();
}
int x;
for(int i=1;i<=q;i++)
{
scanf("%d",&x);
if(i!=q)
printf("%s ",name[num[x]]); //按照已经存入数组的编号 输出名字
else
printf("%s\n",name[num[x]]);
}
}
return 0;
}