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.
题目又臭又长就不贴了,给两串数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.
相关文章推荐
- poj 1442 Black Box
- POJ&nbsp;2160&nbsp;BOX
- POJ Black Box 1442(优先队列)
- poj--1442--black box
- POJ 1703 Find them, Catch them
- POJ 2236 Wireless Network
- POj 2255
- POj 1013 Counterfeit Dollar
- POJ 2247 Humble Numbers
- POJ 3278 Catch That Cow
- Search Box
- POJ 1002 487-3279
- POJ 1050 To the Max
- ZZULI_SummerPractice(3) POJ 3598…
- ZZULI_SummerPractice(3) POJ 308…
- POJ 1256 Anagram(全排列问题)
- POJ 1182 食物链
- HDU:1063 POJ:1001 Exponentiat…
- POJ 1019 Number Sequence
- ZZULI_SummerPractice(3) POJ 12…