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