Phoenix and Memory

Phoenix is trying to take a photo of his n friends with labels 1,2,…,n who are lined up in a row in a special order. But before he can take the photo, his friends get distracted by a duck and mess up their order.

Now, Phoenix must restore the order but he doesn’t remember completely! He only remembers that the i-th friend from the left had a label between ai and bi inclusive. Does there exist a unique way to order his friends based of his memory?

Input
The first line contains one integer n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 ) n (1≤n≤2⋅10^5) n(1n2105) — the number of friends.

The i-th of the next n lines contain two integers a i a_i ai and b i ( 1 ≤ a i ≤ b i ≤ n ) bi (1≤a_i≤b_i≤n) bi(1aibin) — Phoenix’s memory of the i-th position from the left.

It is guaranteed that Phoenix’s memory is valid so there is at least one valid ordering.

Output
If Phoenix can reorder his friends in a unique order, print YES followed by n integers — the i-th integer should be the label of the i-th friend from the left.

Otherwise, print NO. Then, print any two distinct valid orderings on the following two lines. If are multiple solutions, print any.

Examples

input
4
4 4
1 3
2 4
3 4
output
YES
4 1 2 3 
input
4
1 3
2 4
3 4
2 3
output
NO
1 3 4 2 
1 2 4 3 

定义以下变量:
s e q [ i ] seq[i] seq[i]:按照区间先右端点后左端点从小到大排序后第 i i i个区间在原序列的位置。
p o s [ i ] pos[i] pos[i]:第 i i i个人原来的位置。
m p [ i ] mp[i] mp[i]:原来第 i i i个人现在的位置。
p o s i , p o s j posi,posj posi,posj:现在序列中的两个位置对应的人,在恢复原序列后交换这两个人仍满足条件。
解决这个问题的大致思路是首先找到满足条件的答案,再在这个答案的基础上寻找其他满足条件的答案。
找到满足条件的答案需要进行贪心,贪心策略是先将当前序列按照区间右端点从小到大排序,然后按此顺序,对于每个区间,寻找在此区间内的最小位置。
得到满足条件的序列 p o s pos pos后,如果存在 p o s i , p o s j posi,posj posiposj则应满足 a [ p o s j ] ≤ p o s [ p o s i ] < p o s [ p o s j ] ≤ b [ p o s i ] a[posj]≤pos[posi]a[posj]pos[posi]<pos[posj]b[posi]
m p [ i ] = p o s i , m p [ j ] = p o s j mp[i]=posi,mp[j]=posj mp[i]=posi,mp[j]=posj,则 a [ m p [ j ] ] ≤ i < j ≤ b [ m p [ i ] ] a[mp[j]]≤ia[mp[j]]i<jb[mp[i]]
枚举 i i i寻找 j j j,使得 a [ m p [ j ] ] ≤ a [ m p [ k ] ] ∀ k ∈ [ i + 1 , i + b [ m p [ i ] ] ] a[mp[j]]≤a[mp[k]]\quad\forall k\in\mathbb [i+1,i+b[mp[i]]] a[mp[j]]a[mp[k]]k[i+1,i+b[mp[i]]]。如果 a [ m p [ j ] ] ≤ i a[mp[j]]≤i a[mp[j]]i,则更新 p o s i posi posi p o s j posj posj。查找区间最值过程可用线段树维护。

#include

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define vi vector
#define vc vector
#define pii pair
#define pll pair
#define pil pair
#define pli pair
#define mii unordered_map
#define msi unordered_map
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 2e5 + 10;
int n, a[N], b[N];
int seq[N], pos[N], mp[N];

struct Tree2 {
    struct {
        int l, r;
        int dat;
    } t[N * 4];

    void build(int p, int l, int r) {
        t[p].l = l, t[p].r = r;
        if (l == r) {
            return;
        }
        int mid = (l + r) >> 1;
        build(p << 1, l, mid);
        build(p << 1 | 1, mid + 1, r);
    }

    void change(int p, int x, ll v) {
        if (t[p].l == t[p].r) {
            t[p].dat = v;
            return;
        }
        int mid = (t[p].l + t[p].r) >> 1;
        if (x <= mid)change(p << 1, x, v);
        else change(p << 1 | 1, x, v);
        t[p].dat = (a[mp[t[p << 1].dat]] < a[mp[t[p << 1 | 1].dat]]) ? t[p << 1].dat : t[p << 1 | 1].dat;
    }

    int ask(int p, int l, int r) {
        if (l <= t[p].l && r >= t[p].r)return t[p].dat;
        int mid = (t[p].l + t[p].r) >> 1;
        int val = 0;
        if (l <= mid) {
            int tmp = ask(p << 1, l, r);
            val = (a[mp[val]] < a[mp[tmp]]) ? val : tmp;
        }
        if (r > mid) {
            int tmp = ask(p << 1 | 1, l, r);
            val = (a[mp[val]] < a[mp[tmp]]) ? val : tmp;
        }
        return val;
    }
} tr2;

struct Tree1 {
    struct {
        int l, r;
        int dat;
    } t[N * 4];

    void build(int p, int l, int r) {
        t[p].l = l, t[p].r = r;
        if (l == r) {
            t[p].dat = INF;
            return;
        }
        int mid = (l + r) >> 1;
        build(p << 1, l, mid);
        build(p << 1 | 1, mid + 1, r);
        t[p].dat = INF;
    }

    void change(int p, int x, int v) {
        if (t[p].l == t[p].r) {
            t[p].dat = v;
            return;
        }
        int mid = (t[p].l + t[p].r) >> 1;
        if (x <= mid)change(p << 1, x, v);
        else change(p << 1 | 1, x, v);
        t[p].dat = min(t[p << 1].dat, t[p << 1 | 1].dat);
    }

    int ask(int p, int l, int r) {
        if (l <= t[p].l && r >= t[p].r)return t[p].dat;
        int mid = (t[p].l + t[p].r) >> 1;
        int val = INF;
        if (l <= mid)val = min(val, ask(p << 1, l, r));
        if (r > mid)val = min(val, ask(p << 1 | 1, l, r));
        return val;
    }
} tr1;

bool cmp(int x, int y) {
    return b[x] < b[y];
}

int main() {
    n = qr();
    repi(i, 1, n)a[i] = qr(), b[i] = qr(), seq[i] = i;
    tr2.build(1, 1, n), a[0] = INF;
    sort(seq + 1, seq + 1 + n, cmp);
    tr1.build(1, 1, n);
    repi(i, 1, n)tr1.change(1, i, i);
    repi(i, 1, n) {
        pos[seq[i]] = tr1.ask(1, a[seq[i]], b[seq[i]]);
        mp[pos[seq[i]]] = seq[i];
        tr1.change(1, pos[seq[i]], n);
    }
    repi(i, 1, n) tr2.change(1, i, i);
    int posi = 0, posj = 0;
    repi(i, 1, n) if (a[mp[tr2.ask(1, i + 1, b[mp[i]])]] <= i) {
            posi = mp[i], posj = mp[tr2.ask(1, i + 1, b[mp[i]])];
            break;
        }
    if (posi) {
        puts("NO");
        repi(i, 1, n)printf("%d%c", pos[i], ce(i, n));
        swap(pos[posi], pos[posj]);
        repi(i, 1, n)printf("%d%c", pos[i], ce(i, n));
    } else {
        puts("YES");
        repi(i, 1, n)printf("%d%c", pos[i], ce(i, n));
    }
    return 0;
}

你可能感兴趣的:(ACM)