1. 程式人生 > >HDU6301 Distinct Values(2018HDU多校聯賽第一場,思路,貪心,set)

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;
}