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”也是满足题意的,但是字典序不是最小的。
 
做法:先按升高排序,然后我们开始构造数列,身高位ai的人应该加入到从左到右第(bi + 1) 个空位置或者第(当前总人数 - bi + 1)个空位置,显然为了字典序最小我们应该对两者取一个min,看到数据范围,
自然想到线段树维护。
 
代码如下:
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <queue>
 5 #include <algorithm>
 6 #define N 200007
 7 using namespace std;
 8 int n, tot, d[N * 4], M, list[N];
 9 struct arr{
10     int h, s;
11 }a[N];
12 
13 int Cmp(arr x, arr y)
14 {
15     return x.h < y.h;
16 }
17 
18 inline void Build(int n)
19 {
20     for (M = 1; M < n; M <<= 1);
21     for (int i = M; i <= M + n - 1; i++)    d[i] = 1;
22     for (int i = M - 1; i; --i)    d[i] = d[i << 1] + d[i << 1 | 1];
23 }
24 
25 inline void Change(int x)
26 {
27     d[x = M + x - 1] = 0;
28     while (x)    d[x >>= 1] = d[x << 1] + d[x << 1 | 1];    
29 }
30 
31 inline int Find(int x, int ain)
32 {
33     while (x < M)
34     {
35         if (d[x] >= ain)    x = x << 1;
36         else ain -= d[x], x = x | 1;
37     }
38     if (ain == 1 && d[x])    return x - M + 1;
39     else return x - M + 2;
40 }
41 
42 int main()
43 {
44     freopen("queue.in", "r", stdin);
45     freopen("queue.out", "w", stdout);
46     scanf("%d", &n);
47     for (int i = 1; i <= n; i++)
48         scanf("%d%d", &a[i].h, &a[i].s);
49     sort(a + 1, a + n + 1, Cmp);
50     Build(n);
51     for (int i = 1; i <= n; i++)
52     {
53         if (a[i].s > n - i)
54         {
55             printf("impossible");
56             return 0;
57         }
58         int q = Find(1, a[i].s + 1), p = Find(1, n - i - a[i].s + 1);
59         if (q < p)
60         {
61             list[q] = a[i].h;
62             Change(q);
63         }
64         else
65         {
66             list[p] = a[i].h;
67             Change(p);
68         }
69     }
70     for (int i = 1; i <= n; i++)
71         printf("%d ", list[i]);
72 }
View Code