Q - Queue HDU - 5493

Problem Description NNN people numbered from 1 to NNN 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 iii-th person as

hih_ihi​. The iii-th person remembers that there were kik_iki​ 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 kik_iki​ in

a wrong direction. kik_iki​ could be either the number of taller people

before or after the iii-th person. Can you help them to determine the

original order of the queue?

Input The first line of input contains a number TTT indicating the

number of test cases (T≤1000T≤1000T≤1000). Each test case starts with a line

containing an integer NNN indicating the number of people in the queue

(1≤N≤1000001≤N≤1000001≤N≤100000). Each of the next NNN lines consists of two integers

hih_ihi​ and kik_iki​ as described above (1≤hi≤109,0≤ki≤N−11≤h_i≤10^9,0≤k_i≤N-11≤hi​≤109,0≤ki​≤N−1). Note that

the order of the given hih_ihi​ and kik_iki​ is randomly shuffled. The sum

of NNN over all test cases will not exceed 10610^6106

Output For each test case, output a single line consisting of “Case

#X: S”. XXX is the test case number starting from 1. SSS 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.

  1. Sample Input
  2. 3
  3. 3
  4. 10 1
  5. 20 1
  6. 30 0
  7. 3
  8. 10 0
  9. 20 1
  10. 30 0
  11. 3
  12. 10 0
  13. 20 0
  14. 30 1
  15. Sample Output
  16. Case #1: 20 10 30
  17. Case #2: 10 20 30
  18. Case #3: impossible

思路

利用插空的思想, 当我们考虑 某个人 要被放到那个位置上的时候, 考到 可能是比他 高到k个人在他的前边,也可能是比他高到人在他的后边,这个是我们可 把题上给我们的序列按照从身高从小的到大来排序,这我正考虑要某个要放哪的时候是不会受 前边人已经安排好为位置的人影响,,这操作之后这个题目看起来简单些,,,接着由于字典序最小,,,由于每个人的身高是从小到大排序的,所以我们在 决定某个人要被放到 那个位置的时候(这个时候有多个位置符合题意) 我们应该尽量的把这个人放置的越靠前位置越好(在这个位置是符合题意的时候), 那么我们怎判断某个人因该放那个位置呢??我们可以假设 我们要放置的是 第 i 个人,在他的前边或后边 有k个人比他高, 可以确定已经有 i - 1 个人已经被的位置已经被确定了,我们先讨论第一个中情况:在 i 这个人的前边有 k 个人比他高, ⚠️之前放置的人,都比他矮,所以我们要预留 k + 1个空位置(因为 i 这个人也要占一个位置),具体找这个位置,我们可以通过 二分查找 来查找 前缀区间和为 k + 1 的位置 ; 接下来我们讨论第二种情况:在 区间的尾部留 k空位置,那么在这个空位置的前边剩余的空位置为 n - i - k + 1 , 这样在用二分 来查找 区间前缀和为 n - i - k + 1 的位置的下标,由于字典序最小我们应在两种情况的到的位置中取最小的情况,并在把这个位置 天上这个人的身高就行了。。。。。。。这样不断遍历循环讨论下去,就能得到答案了

代码

  1. #include<stdio.h>
  2. #include<string>
  3. #include<string.h>
  4. #include<cstdio>
  5. #include<algorithm>
  6. #include<iostream>
  7. using namespace std;
  8. typedef long long ll;
  9. const int MAXN=200000+5; //最大元素个数
  10. int n;//元素个数
  11. int c[MAXN],ans[MAXN]; //c[i]==A[i]+A[i-1]+...+A[i-lowbit(i)+1]
  12. int lowbit(int i){return i&(-i);} //返回i的二进制最右边1的值
  13. int sum(int x){ //返回A[1]+...A[i]的和
  14. int sum = 0;
  15. while(x){
  16. sum += c[x];
  17. x -= lowbit(x);
  18. }
  19. return sum;
  20. }
  21. void add(int x, int val){ //令A[i] += val
  22. while(x <= n){
  23. c[x] += val;
  24. x += lowbit(x);
  25. }
  26. }
  27. int find_(int x){ //二分查找
  28. int l=1,r=n,mid;
  29. while(l<r){
  30. mid=(l+r)>>1;
  31. int num=sum(mid);
  32. if(num<x)
  33. l=mid+1;
  34. else
  35. r=mid;
  36. }
  37. return l;
  38. }
  39. int Sch(int num) //二分查找空位数为num 的位置
  40. {
  41. int l = 1, r = n, ans;
  42. while(l <= r)
  43. {
  44. int mid = (l + r) >> 1;
  45. if(Sum(mid) >= num)
  46. r = mid - 1, ans = mid;
  47. else
  48. l = mid + 1;
  49. }
  50. return ans;
  51. }
  52. struct node1{
  53. ll h,v;
  54. }a[MAXN];
  55. ll b[MAXN];
  56. bool cmp(node1 x,node1 y){
  57. return x.h<y.h;
  58. }
  59. int main(){
  60. int t;
  61. t--;
  62. cin>>t;
  63. int kase=0;
  64. while(t--){
  65. kase++;
  66. memset(c,0,sizeof(c));
  67. memset(ans,0,sizeof(ans));
  68. scanf("%lld",&n);
  69. for(int i=1;i<=n;i++){
  70. add(i,1);
  71. scanf("%lld%lld",&a[i].h,&a[i].v);
  72. }
  73. sort(a+1,a+n+1,cmp);
  74. int flag=1;
  75. for(int i=1;i<=n;i++){
  76. if(n-i-a[i].v<0) {flag=0;break;}
  77. int p=min(a[i].v,n-i-a[i].v)+1; //前面有多少个空位,包括本身,所以+1
  78. int pos=find_(p);
  79. add(pos,-1);
  80. ans[pos]=a[i].h;
  81. }
  82. printf("Case #%d:", kase);
  83. if (flag) {
  84. for (int i = 1; i <= n; i++) {
  85. printf(" %d", ans[i]);
  86. }printf("\n");
  87. }
  88. else printf(" impossible\n");
  89. }
  90. return 0;
  91. }
  • 总结:1. 对待这种插空位置,我们应该按照一定的顺序,比如这一题 按身高从低到高 去一一的对待去讨论, 这样避免一些了复杂的东西。
  • 2.这里的 “字典序最小” 与 “预留空位的操作” ,是奇妙的搭配
  • 3.这一题的 树状数组 用来统计 空位置 的数量, 而一个又一个讨论找符合题意的下标位置 是很浪费时间的,所以加上了 一个快速 “二分” , 快速查找就非常完美了

Q - Queue HDU - 5493(树状树组维护区间前缀和 + 二分找预留空位)的更多相关文章

  1. HDU 5877 dfs+ 线段树(或+树状树组)

    1.HDU 5877  Weak Pair 2.总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个 3.思路:利用dfs遍历子节点,同时对于每个子节点au, ...

  2. G - Queue HDU - 5493 线段树+二分

    G - Queue HDU - 5493 题目大意:给你n个人的身高和这个人前面或者后面有多少个比他高的人,让你还原这个序列,按字典序输出. 题解: 首先按高度排序. 设每个人在其前面有k个人,设比这 ...

  3. 牛客练习赛38 D 题 出题人的手环 (离散化+树状数组求逆序对+前缀和)

    链接:https://ac.nowcoder.com/acm/contest/358/D来源:牛客网 出题人的手环 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他 ...

  4. 关于线段树or 树状树状 在二维平面搞事情!Orz

    第一式:https://ac.nowcoder.com/acm/contest/143/I 题意: 有 n 个点,一个点集 S 是好的,当且仅当对于他的每个子集 T,存在一个右边无限长的矩形,使得这个 ...

  5. 「BZOJ1537」Aut – The Bus(变形Dp+线段树/树状数组 最优值维护)

    网格图给予我的第一反应就是一个状态 f[i][j] 表示走到第 (i,j) 这个位置的最大价值. 由于只能往下或往右走转移就变得显然了: f[i][j]=max{f[i-1][j], f[i][j-1 ...

  6. 洛谷 P3368 【模板】树状数组 2(区间加,单点查询)

    题目链接 https://www.luogu.org/problemnew/show/P3368 树状数组 最基础的用法:https://www.cnblogs.com/yinyuqin/p/1096 ...

  7. A Simple Problem with Integers 多树状数组分割,区间修改,单点求职。 hdu 4267

    A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  8. HDU 5465——Clarke and puzzle——————【树状数组BIT维护前缀和+Nim博弈】

    Clarke and puzzle Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  9. 主席树套树状数组——带修区间第k大zoj2112

    主席树带修第k大 https://www.cnblogs.com/Empress/p/4659824.html 讲的非常好的博客 首先按静态第k大建立起一组权值线段树(主席树) 然后现在要将第i个值从 ...

随机推荐

  1. 微信WXSS样式文件

    目录 WXSS官方文档 1. WXSS 1.1. 尺寸单位 1.2. 样式导入 1.3. 内联样式 1.4. 选择器 1.5. 全局样式与局部样式 WXSS官方文档 https://developer ...

  2. java 发送邮件详细讲解

    一.JavaMail概述:        JavaMail是由Sun定义的一套收发电子邮件的API,不同的厂商可以提供自己的实现类.但它并没有包含在JDK中,而是作为JavaEE的一部分. 厂商所提供 ...

  3. mysql的锁与事务

    1. MySQL中的事物 1.InnoDB事务原理 1. 事务(Transaction)是数据库区别于文件系统的重要特性之一,事务会把数据库从一种一致性状态转换为另一种一致性状态. 2. 在数据库提交 ...

  4. openwrt 外挂usb 网卡 RTL8188CU 及添加 RT5572 kernel支持

    RT5572 原来叫 Ralink雷凌 现在被 MTK 收购了,淘宝上买的很便宜50块邮,2.4 5G 双频.在 win10 上插了试试,果然是支持 5G.这上面写着 飞荣 是什么牌子,有知道的和我说 ...

  5. flink RPC(akka)

    flink中的rpc框架使用的akka.在本节并不详细讲述akka,而是就flink中rpc来讲述akka的部分内容.本节,我从AkkaRpcActor.handleRpcInvocation方法讲起 ...

  6. Simulink仿真入门到精通(十七) Simulink代码生成技术详解

    17.1 基于模型的设计 基于模型设计是一种流程,较之传统软件开发流程而言,使开发者能够更快捷.更高效地进行开发.适用范围包括汽车电子信号处理.控制系统.通信行业和半导体行业. V字模型开发流程整体描 ...

  7. 区间DP(力扣1000.合并石头的最低成本)

    一.区间DP 顾名思义区间DP就是在区间上进行动态规划,先求出一段区间上的最优解,在合并成整个大区间的最优解,方法主要有记忆化搜素和递归的形式. 顺便提一下动态规划的成立条件是满足最优子结构和无后效性 ...

  8. mongo密码的设置

    MongoDB 版本 v4.0.7 系统 Win10 注意: 要为数据库创建用户,必须先切换到相应的数据库: 要为数据库创建用户,必须先切换到相应的数据库: 要为数据库创建用户,必须先切换到相应的数据 ...

  9. 测试必知必会系列- Linux常用命令 - history

    21篇测试必备的Linux常用命令,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1672457.html 查看历 ...

  10. tomcat 对 vue的history默认支持 tomcat 开启步骤 1.build文件放入webapps目录 2.进入conf目录修改server.xml端口号改成8088 3.进入bin目录运行startup.bat 4.浏览器 localhost:8088/workName 访问即可

    tomcat 对 vue的history默认支持 tomcat 开启步骤 1.build文件放入webapps目录 2.进入conf目录修改server.xml端口号改成8088 3.进入bin目录运 ...