5456. 【NOIP2017提高A组冲刺11.6】奇怪的队列
(File IO): input:queue.in output:queue.out
Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits
Goto ProblemSet做法:先按升高排序,然后我们开始构造数列,身高位ai的人应该加入到从左到右第(bi + 1) 个空位置或者第(当前总人数 - bi + 1)个空位置,显然为了字典序最小我们应该对两者取一个min,看到数据范围,
自然想到线段树维护。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }