【hdu 6301】Distinct Values(区间)

Problem  Description:

Chiaki has an array of n positive integers. You are told some facts about the array: for every two elements ai and aj in the subarray al..r (l≤i<j≤r), ai≠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 T, indicating the number of test cases. For each test case:

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

It is guaranteed that neither the sum of all n nor the sum of all m exceeds 106.

Output:

For each test case, output n 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

题意:寻找一组长度为n的最小数组,并且L到r里面不能有相等的数。输入中的n是数组的长度,m表示有m组L,r数据

思路:这道题要用到set和区间的知识点。主要思想是找一个指针,判断指针是否在区间内,若指针比区间的左界还小,说明指针指向的数对此区间无影响,此时就可以把这个数送回到set中。

My  DaiMa:

#include<bits/stdc++.h>
//#include<set>
using namespace std;
const int Max = 1e5+5;
int main()
{
    int pre[Max],a[Max],t,n,m,l,r;//pre用来记录区间的左界,数组a是要求的数组
    while(~scanf("%d",&t))
    {
        while(t --)
        {
            scanf("%d%d",&n,&m);
            for( int i = 1;i <= n;i ++) pre[i] = i;//定义每个的初始区间
            while(m --)
            {
                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]);//继续对每个区间的左界进行优化,其实这个for循环是用来更新pre[i]到i的每个区间的左界,因为上面输入的时候更新的只是i的区间左界
            set<int> s;
            for(int i = 1;i <= n;i ++) s.insert(i);//初始化set
            int flag = 1;//flag用来与区间的左界进行比较
            for(int i = 1;i <= n;i ++)
            {
                while(flag < pre[i])//如果flag比区间的左界还要小的话,说明flag指向的数对区间没有影响
                {
                    s.insert( a[flag]);//就可以把flag所指向的数送回set里
                    flag++;//接着判断下一个
                }
                a[i] = *s.begin();//为了使最终的数组是最小数组,每次使用的都是set中的第一个数
                s.erase(a[i]);//用完以后以免重复,要删除使用过的元素
            }
            for( int i = 1;i < n;i ++)
                printf("%d ",a[i]);
            printf("%d\n",a[n]);
        }
    }
}

最后附精美照片一枚

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值