http://poj.org/problem?id=3481

题目大意:给你一系列操作,0代表读入终止,1代表添加一个编号为k,权值为p的点,2代表输出权值最大点的编号并删除该点,3代表输出权值最小的点并删除该节点。

treap的操作方法就不具体说了,只解释一些地方,见代码

program haha;
type
   node	= record
	     ls,rs,r,data,num : longint;
	  end;		      
var
   a		: array[0..1000005] of node;
   p,i,j,k,x	: longint;
   y,t,tot,root	: longint;
procedure left(var x: longint);
var
   t : longint;
begin
   t:=a[x].ls;
   a[x].ls:=a[t].rs;
   a[t].rs:=x;
   x:=t;
end; { left }
procedure right(var x : longint);
var
   t : longint;
begin
   t:=a[x].rs;
   a[x].rs:=a[t].ls;
   a[t].ls:=x;
   x:=t;
end; { right }
procedure insert(var x,k,y: longint);
begin
   if x=0 then
   begin
      inc(tot);
      x:=tot;
      a[x].data:=y;
      a[x].ls:=0;
      a[x].rs:=0;
      a[x].num:=k;
      a[x].r:=random(1000000);
      exit;
   end;
   if y>a[x].data then
   begin
      insert(a[x].rs,k,y);//返回值给a[x].rs赋值,从而构建出树
      if a[a[x].rs].r>a[x].r then{!}
	 right(x);
      exit;
   end;
   if y<a[x].data then
   begin
      insert(a[x].ls,k,y);
      if a[a[x].ls].r>a[x].r then
	 left(x);
      exit;
   end;
end; { insert }
procedure delete(var x,k : longint);
begin
   if a[x].data=k then
   begin
      if (a[x].ls=0) or (a[x].rs=0) then
      begin
	 if a[x].ls=0 then
	 begin
	    x:=a[x].rs;
	    exit;
	 end;
	 if a[x].rs=0 then
	 begin
	    x:=a[x].ls;
	    exit;
	 end;
      end;
      if a[a[x].ls].r>a[a[x].rs].r then//如果该节点儿子节点不为空,就旋转,将所要删除的节点旋转到下面,直到该点有叶子
      begin
	 left(x);
	 delete(a[x].rs,k);
	 exit;
      end;
      if a[a[x].rs].r>a[a[x].ls].r then{!}//标记!的两个地方是不一样的:1.插入节点,只需调整插入的和原有的。2.删除节点,为了保证优先级排列的顺序,且由于该节点要删除,所以比较儿子节点再旋转
      begin
	 right(x);
	 delete(a[x].ls,k);
	 exit;
      end;
   end;
   if a[x].data>k then
      delete(a[x].ls,k)
   else
      delete(a[x].rs,k);
end; { delete }
function findmin(x : longint):longint;
begin
   if a[x].ls=0 then
      exit(x);
   if a[x].ls<>0 then
      exit(findmin(a[x].ls));
end; { findmin }
function findmax(x : longint):longint;
begin
   if a[x].rs=0 then
      exit(x);
   if a[x].rs<>0 then
      exit(findmax(a[x].rs));
end; { findmax }
begin
   assign(input,'sdf.in'); reset(input);
   randomize;
   root:=0;
   read(p);
   while p<>0 do
   begin
      if p=1 then
      begin
	 readln(x,y);
	 insert(root,x,y);
      end;
      if p=2 then
      begin
	 t:=findmax(root);//不能从1开始找,因为root的值是改变的,比如,根节点只有左儿子,那么就会删除根节点,此时root的值就会改变
	 writeln(a[t].num);
	 delete(root,a[t].data);
      end;
      if p=3 then
      begin
	 t:=findmin(root);
	 writeln(a[t].num);
	 delete(root,a[t].data);
      end;
      read(p);
   end;
   close(input);
end.//最需要注意的是,所有的过程都需要用var,因为值是会改变的

posted on 2012-04-01 09:12  淡·雅·墨  阅读(475)  评论(0编辑  收藏  举报