HDU - 5493(线段树)

网友投稿 529 2022-08-26

HDU - 5493(线段树)

HDU - 5493(线段树)

NN people numbered from 1 to NN are waiting in a bank for service. They all stand in a queue, but the queue never moves. It is lunch time now, so they decide to go out and have lunch first. When they get back, they don’t remember the exact order of the queue. Fortunately, there are some clues that may help.  Every person has a unique height, and we denote the height of the ii-th person as hihi. The ii-th person remembers that there were kiki people who stand before him and are taller than him. Ideally, this is enough to determine the original order of the queue uniquely. However, as they were waiting for too long, some of them get dizzy and counted kiki in a wrong direction. kiki could be either the number of taller people before or after the ii-th person.  Can you help them to determine the original order of the queue?

Input

The first line of input contains a number TT indicating the number of test cases (T≤1000T≤1000).  Each test case starts with a line containing an integer NN indicating the number of people in the queue (1≤N≤1000001≤N≤100000). Each of the next NN lines consists of two integers hihi and kiki as described above (1≤hi≤109,0≤ki≤N−11≤hi≤109,0≤ki≤N−1). Note that the order of the given hihi and kiki is randomly shuffled.  The sum of NN over all test cases will not exceed 106106

Output

For each test case, output a single line consisting of “Case #X: S”. XX is the test case number starting from 1. SS is people’s heights in the restored queue, separated by spaces. The solution may not be unique, so you only need to output the smallest one in lexicographical order. If it is impossible to restore the queue, you should output “impossible” instead.

Sample Input

3 3 10 1 20 1 30 0 3 10 0 20 1 30 0 3 10 0 20 0 30 1

Sample Output

Case #1: 20 10 30 Case #2: 10 20 30 Case #3: impossible

题目大意:

给出n个人的身高,和在他前面或后面比他高的人的数量。

输出这n个人的顺序,按字典序从小到大输出。不存在就输出impossible。

思路:

先把n个数的线段树建好。

把n个人按身高排序。

题目中有两个方向,就比较这个人位置的两种可能。然后再插入到线段树中。

如第i个人,前面有k个人比他高。则需空出k个位置,或者n-i-k个位置。比较之后,取小值。

代码

#include #include #include #include #include #include #include using namespace std;#define ll long longconst int maxn = 1e5 + 10;const int INF = 0x3f3f3f3f;struct node{ int v, id;}G[maxn];int cmp(node a, node b){ return a.v < b.v;}int sum[maxn * 5];int W[maxn * 4];int ans;int n;void build(int l, int r, int rt){ sum[rt] = r - l + 1; if (l == r) { W[rt] = 0; return; } int m = (l + r) / 2; build(l, m, rt << 1); build(m + 1, r, rt << 1 | 1);}void update(int id, int w, int l, int r, int rt){ sum[rt]--; if (l == r) { W[rt] = w; return; } int m = (l + r) / 2; if (sum[rt << 1] > id)update(id, w, l, m, rt << 1); else update(id - sum[rt << 1], w, m + 1, r, rt << 1 | 1);}void go(int l, int r, int rt){ if (l == r) { ans++; if (ans != n)printf("%d ", W[rt]); else printf("%d\n", W[rt]); return; } int m = (l + r) / 2; go(l, m, rt << 1); go(m + 1, r, rt << 1 | 1);}int main(){ int t; scanf("%d", &t); int T = 1; while (t--) { ans = 0; scanf("%d", &n); memset(sum, 0, sizeof(sum)); memset(W, 0, sizeof(W)); for (int i = 1;i <= n;i++) { int v, id; scanf("%d%d", &v, &id); G[i].v = v;G[i].id = id; } sort(G + 1, G + n + 1, cmp); build(1, n, 1); int flag = 0; for (int i = 1;i <= n;i++) { int id = G[i].id; int v = G[i].v; int id1 = id; int id2 = n - id - i; if (i + id > n) { flag = 1; break; } id = min(id1, id2); update(id, v, 1, n, 1); } printf("Case #%d: ", T++); if (!flag) { go(1, n, 1); } else { printf("impossible\n"); } } return 0;}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:通俗讲解:缓存、缓存算法和缓存框架(简述缓存的分类缓存的工作原理)
下一篇:Android Fragment生命周期深入探究
相关文章

 发表评论

暂时没有评论,来抢沙发吧~