您的位置:首页 > 其它

poj 1442 Black Box

2014-12-29 08:39 344 查看
http://poj.org/problem?id=1442

题目又臭又长就不贴了,给两串数a[i],u[i]长度分别为M,N(我读入的时候是N,M。习惯了。。。)。对于每个u[i],输出a数组前u[i]个中从小到大的第i个数。

//================================================================================================

其实这道题可以用大根堆+小根堆做的,但是为了练手就用Treap硬搞掉了。。。

大根堆+小根堆的做法就是保证大根堆的大小为i,每次加入新数先入大根堆,弹出堆顶的数,把这个数放入小根堆,询问的时候就是大根堆堆顶的数,处理下一个u[i+1]的时候从小根堆弹出堆顶的数加入大根堆。

就是弹来弹去的。。。YY下就出来了。。。不过我还没有实现,如果有错求指教、、

Treap这个就不用说了吧,都是Treap的基本操作:加入一个数。询问k大的数。

一开始在询问k大值调用函数find的时候当过程用了。。。值没有传上去。。。

竟然浪费了时间去调这种错误、、、不可饶恕啊!!!

 

AC
CODE


 

program pku_1442;

const maxn=99999999;

var val,a,fix,sum,left,right:array[0..30000] of longint;

   
root,n,m,i,x,now,num,z,tot:longint;

//============================================================================

procedure right_rotate(var k:longint);

var t:longint;

begin

  t:=left[k];

  sum[k]:=sum[right[t]]+sum[right[k]]+1;

  left[k]:=right[t];

  right[t]:=k; k:=t;

  sum[k]:=sum[left[k]]+sum[right[k]]+1;

end;

//============================================================================

procedure left_rotate(var k:longint);

var t:longint;

begin

  t:=right[k];

  right[k]:=left[t];

  sum[k]:=sum[left[t]]+sum[left[k]]+1;

  left[t]:=k; k:=t;

  sum[k]:=sum[left[k]]+sum[right[k]]+1;

end;

//============================================================================

procedure ins(var k:longint);

begin

  if k=0 then

  begin

    inc(tot);
k:=tot;

    a[k]:=z;
sum[k]:=1;

   
fix[k]:=random(maxn);

    exit;

  end;

  if z<a[k] then

  begin

   
ins(left[k]); sum[k]:=sum[left[k]]+sum[right[k]]+1;

    if
fix[left[k]]>fix[k] then right_rotate(k);

  end else

  begin

   
ins(right[k]); sum[k]:=sum[left[k]]+sum[right[k]]+1;

    if
fix[right[k]]>fix[k] then left_rotate(k);

  end;

end;

//============================================================================

function find(k:longint):longint;

begin

  if sum[left[k]]=num-1 then exit(a[k]) else

  if sum[left[k]]>=num then
exit(find(left[k]))
else   
//一开始直接写了find(left[k])。。。

  begin

   
num:=num-sum[left[k]]-1;

   
exit(find(right[k]));   
//这里也是。。编程手感实在不行啊。。。。。。。

  end;

end;

//============================================================================

begin

  randomize;

  readln(n,m);

  for i:=1 to n do read(val[i]);

  now:=0; root:=0;

  for i:=1 to m do

  begin read(x);

    while
now<x do

    begin

     
inc(now); z:=val[now];

     
ins(root);

    end;
num:=i;

   
writeln(find(root));

  end;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: