题目链接:点我啊╭(╯^╰)╮
n n n 个人标号为 1 1 1 ~ n n n,顺序被打乱后
第 i i i 个人的标号在 [ L i , R i ] [L_i, R_i] [Li,Ri] 之间
保证答案存在,若答案唯一,则输出唯一答案
若不唯一,则输出任意两种答案
考虑先弄出一组答案:
按照 L i L_i Li 排序,枚举加入 L i L_i Li 后,当前肯定选择 R i R_i Ri 最小的那个人
这样肯定是最贪心的,用一个 s e t set set 维护即可
记标号为 i i i 的人打乱后位置在 p o s i pos_i posi
考虑什么情况下两个人的标号可以交换:
L [ p o s i ] ≤ i ≤ R [ p o s i ] L[pos_i] ≤ i ≤ R[pos_i] L[posi]≤i≤R[posi]
L [ p o s j ] ≤ j ≤ R [ p o s j ] L[pos_j] ≤ j ≤ R[pos_j] L[posj]≤j≤R[posj]
假设 i < j i < j i<j,要满足 i i i 和 j j j 可以交换
必须满足: L [ p o s j ] ≤ i < j ≤ R [ p o s i ] L[pos_j] ≤ i <j ≤ R[pos_i] L[posj]≤i<j≤R[posi]
也就是枚举 i i i,只需要找到一个 j j j 满足上式即可
由于 R [ p o s i ] R[pos_i] R[posi] 已知,也就是在标号为 [ i + 1 , R [ p o s i ] ] [i+1, R[pos_i]] [i+1,R[posi]] 里找到一个 j j j
其 L [ p o s j ] L[pos_j] L[posj] 最小,若 L [ p o s j ] ≤ i L[pos_j] ≤ i L[posj]≤i,则满足交换,这部分可以用线段树实现
注意 i > j i > j i>j 的情况是一样的,但是枚举 i < j i < j i<j 就包括所有情况了
i i i 和 p o s i pos_i posi 绕来绕去要分清楚
#include
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair pii;
const int maxn = 2e5 + 5;
int n, pos[maxn], L[maxn], R[maxn], ans[maxn];
int t[maxn<<2], id[maxn<<2];
vector v[maxn];
set s;
void build(int l, int r, int rt){
if(l == r){
t[rt] = L[pos[l]];
id[rt] = l;
return;
}
int mid = l + r >> 1;
build(l, mid, rt<<1);
build(mid+1, r, rt<<1|1);
if(t[rt<<1] < t[rt<<1|1]) t[rt] = t[rt<<1], id[rt] = id[rt<<1];
else t[rt] = t[rt<<1|1], id[rt] = id[rt<<1|1];
}
pii query(int ql, int qr, int l, int r, int rt){
if(rqr) return {1e9, 0};
if(l>=ql && r<=qr) return {t[rt], id[rt]};
int mid = l + r >> 1; pii ret = {1e9, 0};
ret = min(ret, query(ql, qr, l, mid, rt<<1));
ret = min(ret, query(ql, qr, mid+1, r, rt<<1|1));
return ret;
}
signed main() {
scanf("%d", &n);
for(int i=1; i<=n; i++){
scanf("%d%d", L+i, R+i);
v[L[i]].push_back({R[i], i});
}
for(int i=1; i<=n; i++){
s.insert(v[i].begin(), v[i].end());
pos[i] = (*s.begin()).second;
ans[pos[i]] = i;
s.erase(s.begin());
}
build(1, n, 1);
for(int i=1; i<=n; i++){
if(i + 1 > R[pos[i]]) continue;
pii q = query(i+1, R[pos[i]], 1, n, 1);
int q1 = q.first, q2 = q.second;
if(q1 == 1e9 || q1 > i) continue;
puts("NO");
for(int i=1; i<=n; i++) printf("%d ", ans[i]);
puts(""); swap(ans[pos[i]], ans[pos[q2]]);
for(int i=1; i<=n; i++) printf("%d ", ans[i]);
puts(""); return 0;
}
puts("YES");
for(int i=1; i<=n; i++) printf("%d ", ans[i]);
}