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