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.

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

思路

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

代码

#include<stdio.h>
#include<string>
#include<string.h>
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int MAXN=200000+5; //最大元素个数
int n;//元素个数
int c[MAXN],ans[MAXN]; //c[i]==A[i]+A[i-1]+...+A[i-lowbit(i)+1] int lowbit(int i){return i&(-i);} //返回i的二进制最右边1的值 int sum(int x){ //返回A[1]+...A[i]的和
int sum = 0;
while(x){
sum += c[x];
x -= lowbit(x);
}
return sum;
} void add(int x, int val){ //令A[i] += val
while(x <= n){
c[x] += val;
x += lowbit(x);
}
} int find_(int x){ //二分查找
int l=1,r=n,mid;
while(l<r){
mid=(l+r)>>1;
int num=sum(mid);
if(num<x)
l=mid+1;
else
r=mid;
}
return l;
} int Sch(int num) //二分查找空位数为num 的位置
{
int l = 1, r = n, ans;
while(l <= r)
{
int mid = (l + r) >> 1;
if(Sum(mid) >= num)
r = mid - 1, ans = mid;
else
l = mid + 1;
}
return ans;
} struct node1{
ll h,v;
}a[MAXN]; ll b[MAXN]; bool cmp(node1 x,node1 y){
return x.h<y.h;
} int main(){
int t;
t--;
cin>>t;
int kase=0;
while(t--){
kase++;
memset(c,0,sizeof(c));
memset(ans,0,sizeof(ans));
scanf("%lld",&n);
for(int i=1;i<=n;i++){
add(i,1);
scanf("%lld%lld",&a[i].h,&a[i].v);
} sort(a+1,a+n+1,cmp);
int flag=1;
for(int i=1;i<=n;i++){
if(n-i-a[i].v<0) {flag=0;break;}
int p=min(a[i].v,n-i-a[i].v)+1; //前面有多少个空位,包括本身,所以+1
int pos=find_(p); add(pos,-1);
ans[pos]=a[i].h;
} printf("Case #%d:", kase);
if (flag) {
for (int i = 1; i <= n; i++) {
printf(" %d", ans[i]);
}printf("\n");
}
else printf(" impossible\n");
}
return 0;
}
  • 总结:1. 对待这种插空位置,我们应该按照一定的顺序,比如这一题 按身高从低到高 去一一的对待去讨论, 这样避免一些了复杂的东西。
  • 2.这里的 “字典序最小” 与 “预留空位的操作” ,是奇妙的搭配
  • 3.这一题的 树状数组 用来统计 空位置 的数量, 而一个又一个讨论找符合题意的下标位置 是很浪费时间的,所以加上了 一个快速 “二分” , 快速查找就非常完美了

最新文章

  1. Redis主从复制
  2. java web系统中时间比sql server中的日期少2天的解决办法
  3. c# 无法加载 DLL xxxxxxxx找不到指定的模块。 (异常来自HRESULT:0x8007007E)。的一个解决方法
  4. c语言检测文件是否存在int __cdecl access(const char *, int);
  5. 【HTML】Beginner2:page title
  6. Tomcat的server.xml(中文版)
  7. JavaScript Set Cursor Style
  8. fragement切换动画效果的实现
  9. Vim编译器的常用使用方法与技巧
  10. mapreduce项目中加入combiner
  11. 查看Windows电脑上.NET Framework版本的方法(找了好久的方法)
  12. linux在tomcat中指定jdk
  13. Python-0010-
  14. Java并发编程--5.信号量和障碍器
  15. js学习笔记16----父节点的操作
  16. conda
  17. js-jquery-SweetAlert2【三】INPUT TYPES
  18. XAMPP设置tomcat自启动时,报无效的Win32程序
  19. JDBC 获取被插入数据的主键ID值
  20. Java—maven项目管理

热门文章

  1. dom节点及对节点的常用操作方法
  2. HTML5&amp;CCS3(1) 网页的构造块
  3. js 碰撞+拖拽
  4. (转)C++中的new
  5. 聊聊order by rand()
  6. 基于SIP协议的性能测试——奇林软件kylinPET
  7. Asp.Net Core 3.1 获取不到Post、Put请求的内容 System.NotSupportedException Specified method is not supported
  8. 告别炼丹,Google Brain提出强化学习助力Neural Architecture Search | ICLR2017
  9. drf的频率认证
  10. hdu1072 逃离迷宫系列 bfs