HDU-5437 Alisha’s Party(STL+模拟)

题意:

Alisha过生日,有k个朋友先后到来,且携带价值vi的礼物。Alisha的房间很小,所以她打算开m次门,分别在ti个朋友到达之后,让携带礼物价值前pi高的朋友按礼物价值依次进入房间,如果pi大于在门口等待的人数,则让他们全部进入房间,如果两个人的礼物价值相等,则让先来的人先进。开m次门之后,如果还有没进入过房间的朋友,则让他们按礼物价值依次全部进入房间。最后q个询问,每个询问一个ni,让你求第ni个进入房间的朋友的名字。

思路:

我是用了好几个STL进行的模拟。对于q次询问,我把不同的ni作为键存入map,然后ni所对应的值是第几次询问即i,如果ni在之前出现过,则我把map中ni对应的值即上一次的下标取负存下,在最后输出的时候处理一下再输出即可,这样就实现了logn的取出之后模拟时需要记录的次序,然后对m次开门排个序用set进行模拟就好了。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 15e4+1;
struct node
{
	int id, val;
	bool operator<(const node k)const
	{
		if(val == k.val) return id < k.id;
		return val > k.val;
	}
};
char s[maxn][201];
int v[maxn];
set<node> st;
set<node>::iterator it;
pair<int, int> pr[maxn];
int ned[105];
map<int, int> mp;
map<int, int>::iterator iter;
vector<node> vt;
int T, K, M, Q;
int cmp(pair<int, int> pr1, pair<int, int> pr2)
{return pr1.first < pr2.first;}
int main()
{	
	//freopen("in.txt", "r", stdin);
	int x, pre, id;
	for(scanf("%d", &T); T--;)
	{
		scanf("%d %d %d", &K, &M, &Q);
		for(int i = 1; i <= K; ++i)
		{
			scanf("%s", s[i]);
			scanf("%d", &v[i]);
		}
		for(int i = 1; i <= M; ++i)
		scanf("%d %d", &pr[i].first, &pr[i].second);
		mp.clear();
		for(int i = 1; i <= Q; ++i)
		{
			scanf("%d", &x);
			if(mp.find(x) != mp.end()) ned[i] = -mp[x];
			else mp[x] = i;
		}
		sort(pr+1, pr+M+1, cmp);
		pre = 1, id = 1;
		st.clear();
		for(int i = 1; i <= M; ++i)
		{
			iter = mp.begin();
			int t = iter->first;
			if(pr[i].first-pre+1+st.size() <= pr[i].second && id+
			pr[i].first-pre+1+st.size()-1 < t)
			{
				st.clear();
				id += pr[i].first-pre+1+st.size();
				pre = pr[i].first+1;
				continue;
			}
			for(int j = pre; j <= pr[i].first; ++j)
			st.insert((node){j, v[j]});
			vt.clear();
			for(it = st.begin(); it != st.end() && vt.size() < pr[i].second; ++it)
			vt.push_back(*it);
			while(id+vt.size()-1 >= t)
			{
				ned[mp[t]] = vt[t-id].id;
				mp.erase(t);
				if(mp.empty()) break;
				iter = mp.begin();
				t = iter->first;
			}
			if(mp.empty()) break;
			for(int j = 0; j < vt.size(); ++j)
			st.erase(vt[j]);
			id += vt.size();
			pre = pr[i].first+1;
		}
		if(!mp.empty())
		{
			for(int i = pre; i <= K; ++i)
			st.insert((node){i, v[i]});
			int t = 0;
			for(it = st.begin(); it != st.end() && !mp.empty(); ++it, ++t)
			{
				if(mp.find(id+t) != mp.end())
				{
					ned[mp[id+t]] = it->id;
					mp.erase(id+t);
				}
			}
		}
		for(int i = 1; i <= Q; ++i)
		{
			if(ned[i] < 0) printf("%s", s[ned[-ned[i]]]);
			else printf("%s", s[ned[i]]);
			printf("%c", i==Q?'\n':' ');
		}
	}
	return 0;
}


继续加油~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值