HDU6301 Distinct Values(2018HDU多校联赛第一场,思路,贪心,set)

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

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的序列,要求满足给出m个区间,使这些区间中不能出现相同的数。同时要求字典序最小。

我们首先可以想到贪心。问题转化成求一个区间里的mex(没有出现过且最小的非负整数),由于区间左右端点都是递增的,用个set维护下即可。

我们用:

  • pre[i]来表示能覆盖第i个位置的最前面的位置
  • set来维护当前可以选的数‘’

然后用一个指针,从下标1开始,从左到右依次选,选到当前位置的时候,那么能覆盖当前位置的区间就是[pre[i],i],对于每一个位置,当前指针pl小于pre[i]的时候,证明对应的答案ans[pl]可以插插入这个集合,然后给当前位置选择数字,然后把这个数字从集合中删去,一直维护过去就好了。

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include <list>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int N = 5e5 + 10;
const int inf = 0x3f3f3f3f;
int pre[N], l, r, ans[N]; //pre[i]能覆盖第i个位置的最前面
int main()
{
    //freopen("in.txt", "r", stdin);
    int t, n, m;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
            pre[i] = i;
        for (int i = 1; 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> s;
        for (int i = 1; i <= n; i++)
            s.insert(i);
        for (int i = 1; i <= n; i++)
        {
            while (pl < pre[i])
            {
                s.insert(ans[pl]);
                pl++;
            }
            ans[i] = *s.begin();
            s.erase(ans[i]);
        }
        for (int i = 1; i <= n; i++)
            if (i == 1)
                printf("%d", ans[i]);
            else
                printf(" %d", ans[i]);
        puts("");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/riba2534/article/details/81177482