https://codeforces.com/contest/1348/problem/F
题意:
是否存在唯一的一个 \(1\sim n\) 的排列 \(c[]\) ,满足 \(a_i \leq c_i \leq b_i\) ?
题目保证存在。若排列唯一,输出这个排列;若不唯一,输出两种可能的排列
思路:
首先找一个可行解。贪心,对 \(i=1\to n\),把 \(i\) 放在左端点小于等于 \(i\) 的区间中右端点最小的那一个。做法是先将所有区间按左端点从小到大排序,再用小根堆为每个 \(i\) 找到右端点最小的区间 \(home[i]\)
如果存在另外的解,那么一定能通过交换某两个数字 \(i\) 和 \(j\) 得到。能交换的条件是 \(home[j].a\le i<j\le home[i].b\)
从满足 \(home[j].a\le i\) 的数字 \(J\) 中找一个大于 \(i\) 的最小的数 \(j\),再判断这个数是否满足 \(j\le b\) 。如果 \(j>b\) ,那后面的数字比 \(j\) 还大,更不可能
#include <bits/stdc++.h>
using namespace std;
#define PRINT for(int z=1;z<=n;z++)cout<<ans[z]<<(z<n?' ':'\n')
const int N = 2e5+10;
struct Interval
{
int a, b, id;
bool operator> (Interval tmp) const
{return b > tmp.b; }
} c[N];
vector<int> leftIs[N];
priority_queue<Interval, vector<Interval>, greater<Interval> > qu;
set<int> st;
int home[N], ans[N];
signed main()
{
int n; cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> c[i].a >> c[i].b; c[i].id = i;
leftIs[c[i].a].push_back(i);
}
for(int i = 1; i <= n; i++)
{
for(auto it : leftIs[i]) qu.push(c[it]);
home[i] = qu.top().id;
ans[qu.top().id] = i;
qu.pop();
}
for(int i = 1; i <= n; i++)
{ //把左端点<=i的区间对应的数字加入set
for(auto it : leftIs[i]) st.insert(ans[it]);
auto it = st.upper_bound(i); int j = *it;
if(it != st.end() && j <= c[home[i]].b)
{
puts("NO"); PRINT;
swap(ans[home[i]], ans[home[j]]);
PRINT; return 0;
}
}
puts("YES"); PRINT;
return 0;
}