题目链接:点我啊╭(╯^╰)╮
题目大意:
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<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 2e5 + 5;
int n, pos[maxn], L[maxn], R[maxn], ans[maxn];
int t[maxn<<2], id[maxn<<2];
vector <pii> v[maxn];
set <pii> 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(r<ql || l>qr) 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]);
}