5456. 【NOIP2017提高A组冲刺11.6】奇怪的队列

Description
nodgd的粉丝太多了,每天都会有很多人排队要签名。
今天有?个人排队,每个人的身高都是一个整数,且互不相同。很不巧,nodgd今天去忙别的事情去了,就只好让这些粉丝们明天再来。同时nodgd提出了一个要求,每个人都要记住自己前面与多少个比自己高的人,以便于明天恢复到今天的顺序。
但是,粉丝们或多或少都是有些失望的,失望使她们晕头转向、神魂颠倒,已经分不清楚哪一边是“前面”了,于是她们可能是记住了前面比自己高的人的个数,也可能是记住了后面比自己高的人的个数,而且他们不知道自己记住的是哪一个方向。
nodgd觉得,即使这样明天也能恢复出一个排队顺序,使得任意一个人的两个方向中至少有一个方向上的比他高的人数和他记住的数字相同。可惜?比较大,显然需要写个程序来解决,nodgd很忙,写程序这种事情就交给你了。
 
Input
第一行输入一个整数?,表示指令的条数。
接下来?行,每行两个整数??,??,表示一个人的身高和她记住的数字,保证身高互不相同。
 
Output
输出一行,这个队列里从前到后的每个人的身高。如果有多个答案满足题意,输出字典序最小。如果不存在满足题意的排列,输出“impossible”(不含引号)。
 
Solutions

首先我们可以知道身高最小的“粉丝”的位置,为min(b[i]+1,n-b[i]),

然后找身高第二小的“粉丝”的位置......第n小的“粉丝”的位置。

可以用线段树来维护,tree[l,r,len]表示在l到r这个区间中还有len的位置。

 

代码

 

  1 type
  2   arr=record
  3     l,r,len:longint;
  4   end;
  5 var
  6   n:longint;
  7   tree:array [0..400001] of arr;
  8   a,b,num:array [0..100001] of longint;
  9 procedure qsort(l,r:longint);
 10 var
 11   i,j,mid,t:longint;
 12 begin
 13   if l>r then exit;
 14   i:=l; j:=r;
 15   mid:=a[(l+r) div 2];
 16   repeat
 17     while a[i]<mid do inc(i);
 18     while a[j]>mid do dec(j);
 19     if i<=j then
 20       begin
 21         t:=a[i]; a[i]:=a[j]; a[j]:=t;
 22         t:=b[i]; b[i]:=b[j]; b[j]:=t;
 23         inc(i); dec(j);
 24       end;
 25   until i>j;
 26   qsort(i,r);
 27   qsort(l,j);
 28 end;
 29 
 30 procedure init;
 31 var
 32   i:longint;
 33 begin
 34   readln(n);
 35   for i:=1 to n do
 36     readln(a[i],b[i]);
 37 end;
 38 
 39 procedure build(p,l,r:longint);
 40 var
 41   mid:longint;
 42 begin
 43   tree[p].l:=l; tree[p].r:=r;
 44   tree[p].len:=r-l+1;
 45   if l=r then exit;
 46   mid:=(l+r) div 2;
 47   build(p*2,l,mid);
 48   build(p*2+1,mid+1,r);
 49 end;
 50 
 51 procedure ins(p,t,k:longint);
 52 var
 53   mid:longint;
 54 begin
 55   dec(tree[p].len);
 56   if tree[p].l=tree[p].r then
 57     begin
 58       num[tree[p].r]:=k;
 59       exit;
 60     end;
 61   if tree[p*2].len>=t then ins(p*2,t,k)
 62                       else ins(p*2+1,t-tree[p*2].len,k);
 63 end;
 64 
 65 function min(o,p:longint):longint;
 66 begin
 67   if o<p then exit(o);
 68   exit(p);
 69 end;
 70 
 71 procedure main;
 72 var
 73   i,pos:longint;
 74 begin
 75   build(1,1,n);
 76   for i:=1 to n do
 77     begin
 78       if b[i]>n-i then
 79         begin
 80           write('impossible');
 81           exit;
 82         end;
 83       pos:=min(b[i]+1,n-b[i]-i+1);
 84       ins(1,pos,a[i]);
 85     end;
 86   for i:=1 to n do
 87     write(num[i],' ');
 88 end;
 89 
 90 begin
 91   assign(input,'queue.in');
 92   assign(output,'queue.out');
 93   reset(input);
 94   rewrite(output);
 95   init;
 96   qsort(1,n);
 97   main;
 98   close(input);
 99   close(output);
100 end.

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值