给你一段长度为n的区间,然后在给你m个小区间,要求这m个小区间里的每个人都不能重复,请你输出字典序最小的方案.
我们可以开一个suf数组,表示我到我后面的不出现重复数字的区间至少需要到达的位置。所以对于给出的每一个l,r,suf[l] = max(suf[l], r);
处理好suf数组,在开一个容器,用来表示我现在可以用的数字集合
然后用L变量表示我上一个到达的位置,R变量表示我现在到达的位置。
然后对头扫到尾,如果我现在已经到达的位置比目前 i 的约束条件的位置来的大,说明这个 i 地方我已经判断过了,就可以直接continue到下一步
如果我需要从这个点开始走,那么我就要把这现在这个区间外的值加入到set容器里来,因为这些数对于现在我正在判断的区间是没有影响的。
然后在现在这个区间里每次加入最小的数,然后把这个数从set容器里删除掉
具体看代码
#include<map> #include<set> #include<ctime> #include<cmath> #include<stack> #include<queue> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define first fi #define second se #define lowbit(x) (x & (-x)) typedef unsigned long long int ull; typedef long long int ll; const double pi = 4.0*atan(1.0); const int inf = 0x3f3f3f3f; const int maxn = 100005; const int maxm = 305; using namespace std; int n, m, tol, T; int suf[maxn]; int ans[maxn]; void init() { memset(suf, 0, sizeof suf); memset(ans, 0, sizeof ans); } int main() { scanf("%d", &T); while(T--) { init(); scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) suf[i] = i; for(int i=1; i<=m; i++) { int l, r; scanf("%d%d", &l, &r); suf[l] = max(suf[l], r); } int L = 1; int R = 0; set<int > s; s.clear(); for(int i=1; i<=n; i++) s.insert(i); for(int i=1; i<=n; i++) { if(R >= suf[i]) continue; while(L < i) { s.insert(ans[L]); L++; } while(R < suf[i]) { R++; int x = *s.begin(); ans[R] = x; s.erase(x); } } for(int i=1; i<=n; i++) printf("%d%c", ans[i], i==n ? '\n' : ' '); } return 0; }