HDU 6301 Distinct Values (贪心做法维护mex)技巧

Distinct Values

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3974    Accepted Submission(s): 1334


 

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 (li<jr), aiaj 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≤lirin).

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

 

Source

2018 Multi-University Training Contest 1

 

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  6331 6330 6329 6328 6327 

#include<bits/stdc++.h>
const int maxn=1e5+7;
using namespace std;

int n,m,ans[maxn];
int l,r,pre[maxn];
/*
题目大意:给定m个区间,要求区间内数字各不相同,
构造出这种序列并且要求字典序最小。

大佬的思维就是不一样。。。
用pre[i]数组表示pre[i]到i这个区间一定是各不相同的数字组成的。

最后贪心的用预处理好的pre数组,
比如:现在遍历到i,假设之前的已经处理好了,
pl下标如果没有到达pre[i],就是说pl到pre[i]之间的区间还可以重复利用,
就可以不断的添加到可用集合set中,因为set集合自动排序,
所以特别方便。

*/

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+1],pre[i]);///一种递推思想,pre[i]到i的区间里的数都不相同

        int pl=1;
        set<int> st;
        for(int i=1;i<=n;i++)
        {
            ans[i]=i;
            st.insert(i);
        }

        for(int i=1;i<=n;i++)
        {
            while(pl<pre[i])
            {
                st.insert(ans[pl]);///不断用前面已经构造出的数来填充,贪心做法
                pl++;
            }
            ans[i]=*st.begin();
            st.erase(ans[i]);
        }

        for(int i=1;i<=n;i++) printf("%d%c",ans[i],i==n?'\n':' ');
    }
    return 0;
}

 

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/81304981