【HDU6301】set+贪心

1.题目链接。题目大意:一个长度为n的数组,现在对这个数组做一些限制:在区间[l,r]里面不能有相同的数出现。输出满足条件并且字典序最小的那个数组。

2.思路有很多,不过发现可行的不是很多。大佬的队友用并查集写过了(神仙,完全想不到并查集的思路)。最后的做法就是:对于每一个数据,用pre[i]记录一下与当前的这个点i不能出现相同的数据的最左边的那个位置。也就是pre[i]=min(pre[i],l)注意这里时min,因为在左边,我们要取到最长,一定是去最小的那个。这样一些小的区间其实就被覆盖掉了。然后用pl,set,ret分别维护当前已经完成填充的区间的右端点,当前可以用的元素,以及答案。这样,对于每一个i,我们找到pre[i],比较pre[i]和pl的大小,如果pl<pre[i]表示还是由比较多的元素可以继续使用,我们我们把上一次放在ret里面的东西拿出来再次丢进set,然后ret[i]就是set的起始元素,这里其实就保证了字典序最小,因为set是红黑树,所以里面的元素都是有序的排列的。然后把答案记录一下,在set里面移除这个元素。最后输出即可。

#include<bits/stdc++.h>
using namespace std;
#pragma warning(disable:4996)
const int N = 100100;
int t, n, m, pre[N], l, r, ret[N];
int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; i++)
		{
			pre[i] = i;
		}
		for (int i = 0; i < m; i++)
		{
			scanf("%d%d", &l, &r);
			pre[r] = min(pre[r], l);
		}
		for (int i = n - 1; i >= 1; i--)
		{
			pre[i] = min(pre[i], pre[i + 1]);
		}
		int pl = 1;
		set<int>val;
		for (int i = 1; i <= n; i++)
		{
			val.insert(i);
		}
		for (int i = 1; i <= n; i++)
		{
			if (pl < pre[i])
			{
				while (pl < pre[i])
				{
					val.insert(ret[pl++]);
				}
			}
			ret[i] = *val.begin();
			val.erase(ret[i]);
		}
		for (int i = 1; i <= n; i++)
		{
			if (i != 1)
				cout << " ";
			cout << ret[i];
		}
		puts("");
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值