HDU 6301 Distinct Values ---(贪心+模拟) 2018 Multi-University Training Contest 1

这道题,是我学弟想出来的思路,并且分分钟AC了。嗯,难受的一比。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6301

题意:给你一个长度为n的数组你可以向数组中填数。然后有m个要求,要求包含两个数字,l,r。表示l到r区间的所有值不能相等。求字典序最小的数组。

题解:首先把所有的询问排个序,先按l从小到大,再按r从小到大。这样有利于我们处理区间。

对于任意不相交区间,我们都是让他从1递增的赋值。这样保证字典序最小,这个很好考虑。

但是相交区间

我们设 l1 r1 和 l2 r2相交。

大小关系为 l1  < l2 < r1 < r2

那么我们要更改的值为 r1到r2的位置。我们要更改成什么值呢?

更改为 l1 到 l2 的里从小到大值。若l1--l2 的区间长度 小于 r1 --r2的区间 放完之后,我们还要记录一个 l1 和 r1 的最大的值。然后再从这个最大值递增赋值。当然小于的话就可以直接全部放置。

剩余就是模拟这个贪心过程了。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
struct node{
	int l,r;
};
int n,m;
node q[MAXN];
int a[MAXN];

bool cmp(node a,node b){
	return a.l == b.l ? a.r < b.r : a.l < b.l;
}
int main(){
	int z;
	cin >> z;
	while(z--){
		scanf("%d%d",&n,&m);
		for(int i = 0 ; i < m ; i ++){
			scanf("%d%d",&q[i].l,&q[i].r);
		}
		fill(a+1,a+n+1,1);
		sort(q,q+m,cmp);
		int Max = 1;
		for(int i = q[0].l ; i <= q[0].r ; i ++)
			a[i] = Max++;
		int l = q[0].l ,r = q[0].r;
		priority_queue<int,vector<int>,greater<int>> num;
		set<int> s;
		for(int i = 1 ; i < m ; i ++){
			if(q[i].r <= r) continue;
			if(r < q[i].l){
				Max = 1;
				for(int j = q[i].l ; j <= q[i].r ; j ++){
					a[j] = Max++;
				}
				l = q[i].l;
				r = q[i].r;
			//	while(!num.empty()) num.pop();
			s.clear();
			}
			while(l < q[i].l){
			//	num.push(a[l++]);
				s.insert(a[l++]);
			}
			while(r < q[i].r){
//				if(!num.empty()){
//					a[++r] = num.top();
//					num.pop();
//				} 
				if(s.size() != 0){
					a[++r] = *s.begin();
					s.erase(s.begin());
				}
				else {
					a[++r] = Max++;
				}
			}
		}
		for(int i = 1 ; i <= n; i ++){
			if(i != n){
				printf("%d ",a[i]);
			}
			else printf("%d",a[i]);
		}
		printf("\n");
	}
}

猜你喜欢

转载自blog.csdn.net/pk__pk/article/details/81187653