1. 程式人生 > >[JZOJ5456]【NOIP2017提高A組沖刺11.6】奇怪的隊列

[JZOJ5456]【NOIP2017提高A組沖刺11.6】奇怪的隊列

失望 output 第一個 粉絲 排隊 return algo nod struct

Description

nodgd的粉絲太多了,每天都會有很多人排隊要簽名。
今天有??個人排隊,每個人的身高都是一個整數,且互不相同。很不巧,nodgd今天去忙別的事情去了,就只好讓這些粉絲們明天再來。同時nodgd提出了一個要求,每個人都要記住自己前面與多少個比自己高的人,以便於明天恢復到今天的順序。
但是,粉絲們或多或少都是有些失望的,失望使她們暈頭轉向、神魂顛倒,已經分不清楚哪一邊是“前面”了,於是她們可能是記住了前面比自己高的人的個數,也可能是記住了後面比自己高的人的個數,而且他們不知道自己記住的是哪一個方向。
nodgd覺得,即使這樣明天也能恢復出一個排隊順序,使得任意一個人的兩個方向中至少有一個方向上的比他高的人數和他記住的數字相同。可惜??比較大,顯然需要寫個程序來解決,nodgd很忙,寫程序這種事情就交給你了。

Input

第一行輸入一個整數??,表示指令的條數。
接下來??行,每行兩個整數????,????,表示一個人的身高和她記住的數字,保證身高互不相同。

Output

輸出一行,這個隊列裏從前到後的每個人的身高。如果有多個答案滿足題意,輸出字典序最小。如果不存在滿足題意的排列,輸出“impossible”(不含引號)。

Sample Input

輸入1:
4
4 1
3 1
6 0
2 0
輸入2:
6
1 5
8 0
3 1
4 0
2 0
6 0

Sample Output

輸出1:
2 4 3 6
輸出2:
1 2 4 3 6 8

Data Constraint

n<=100000
ai<=10^9

Hint

【樣例解釋1】
在所給出的答案隊列中,第一個人身高為2,前面有0個人比他高,所以他是輸入的第4個人;第二個人身高為4,右邊有1個人比他高,所以他是輸入的第1個人;第三個人身高為3,右邊有1個人比他高,所以他是輸入的第2個人;第四個人身高為6,左邊有0個人比他高,所以他是輸入的第3個人。
顯然,如果排列為“6 3 4 2”也是滿足題意的,但是字典序不是最小的。


按身高從小到大排序, 然後得到他的rank, 要不插在隊伍前面數第rank+1個空位, 要不就插在從後數的第rank+1位,因為要字典序最小, 所以找到最小的位置插入他。

然後上面的查詢操作可以用線段樹快速實現。

總復雜度O(NlogN)。

沒有輸出impossble掛了10分,AK的夢想破滅了233


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define reg register
inline int read() {
    int res=0;char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48), ch=getchar();
    return res;
}
#define N 100005
int n;
int tr[N<<2];
#define ls(o) o << 1
#define rs(o) o << 1 | 1

inline void update(int o)
{
    tr[o] = tr[ls(o)] + tr[rs(o)];
}

void Build(int l, int r, int o)
{
    if (l == r)
    {
        tr[o] = 1;
        return ;
    }
    int mid = l + r >> 1;
    Build(l, mid, ls(o));
    Build(mid + 1, r, rs(o));
    update(o);
}

void change(int l, int r, int o, int pos)
{
    if (l == r) {tr[o] = 0; return ;}
    int mid = l + r >> 1;
    if (pos <= mid) change(l, mid, ls(o), pos);
    else change(mid + 1, r, rs(o), pos);
    update(o);
}

int query(int l, int r, int o, int k)
{
    if (l == r) return l;
    int mid = l + r >> 1;
    if (tr[ls(o)] >= k) return query(l, mid, ls(o), k);
    else return query(mid + 1, r, rs(o), k - tr[ls(o)]);
}

struct date {
    int h, id;
}p[N];

bool cmp(date a, date b)
{
    return a.h < b.h;
}

int ans[N];

int main()
{
    freopen("queue.in", "r", stdin);
    freopen("queue.out", "w", stdout);
    n = read();
    for (reg int i = 1 ; i <= n ; i ++) p[i].h = read(), p[i].id = read();
    sort(p + 1, p + 1 + n, cmp);
    Build(1, n, 1);
//    for (reg int i = 1 ; i <= n ; i ++) printf("%d\n", p[i].h);
    for (reg int i = 1 ; i <= n ; i ++)
    {
        int k1 = query(1, n, 1, p[i].id + 1);
        int k2 = query(1, n, 1, n - p[i].id - i + 1);
        if (k1 <= k2) 
        {
            ans[k1] = p[i].h;
            change(1, n, 1, k1);
        }
        else {
            ans[k2] = p[i].h;
            change(1, n, 1, k2);
        }
    }
    for (reg int i = 1 ; i <= n ; i ++) printf("%d ", ans[i]);
    return 0;
}

[JZOJ5456]【NOIP2017提高A組沖刺11.6】奇怪的隊列