HDU-6301 set 巧妙的记录区间

首先有请本期主角:~~

Chiaki has an array of nn positive integers. You are told some facts about the array: for every two elements aiai and ajaj in the subarray al..ral..r (l≤i<j≤rl≤i<j≤r), ai≠ajai≠aj holds. 
Chiaki would like to find a lexicographically minimal array which meets the facts. 

Input

There are multiple test cases. The first line of input contains an integer TT, indicating the number of test cases. For each test case: 

The first line contains two integers nn and mm (1≤n,m≤1051≤n,m≤105) -- the length of the array and the number of facts. Each of the next mm lines contains two integers lili and riri (1≤li≤ri≤n1≤li≤ri≤n). 

It is guaranteed that neither the sum of all nn nor the sum of all mm exceeds 106106. 

Output

For each test case, output nn integers denoting the lexicographically minimal array. Integers should be separated by a single space, and no extra spaces are allowed at the end of lines. 

Sample Input

3
2 1
1 2
4 2
1 2
3 4
5 2
1 3
2 4

Sample Output

1 2
1 2 1 2
1 2 3 1 1

【题意】:寻找一个按字典序排列的数列,在给定区间内不能有重复的数字。因此在每个连续区间内每个数字只能出现一次。

【分析】:题目一共有两个主要的问题,第一是如何处理给定的区间,第二个是如何向数列中填入数值,保证在给定区间内不存在相同数字且满足字典序。首先我们采用一种巧妙的方法来确定区间,对于区间我们可以分析出一下三个特性:

1.若区间(a,b)包含于区间(l,r)则可以忽略(a,b);

2.若区间(a,b)(l,r),中a<l < b < r在计算(l,r)时要取出(a,l)之前的所有元素;

3.若区间(a,b)没有被既定,则(a,b)中所有数均为1;

因此我们可以用如下方法:

for(int i=1;i<=n;i++){
            num[i]=i;
		}
		for(int i=0;i<m;i++){
            scanf("%d%d",&l,&r);
            num[l]=max(num[l],r);
		}

最后再用set来确定顺序给出代码

#include <iostream>
#include <set>

using namespace std;

int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int num[100005];
        int res[100005];
        int n,m,l,r;
        scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++){
            num[i]=i;
		}
		for(int i=0;i<m;i++){
            scanf("%d%d",&l,&r);
            num[l]=max(num[l],r);
		}
		set<int>s;
		for(int i=1;i<=n;i++)
            s.insert(i);
        int pi=1;
        for(int i=1;i<=n;i++){
            if(i!=1)
                s.insert(res[i-1]);
            while(pi<=num[i]){
                res[pi]=*s.begin();
                s.erase(res[pi++]);
            }
        }
        for(int i=1;i<n;i++){
            printf("%d ",res[i]);
        }
        printf("%d\n",res[n]);
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值