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