[bzoj1208] [HNOI2004]宠物收养所

本题考查的是数据结构,很基础的平衡树就可以解决,所以本题c++的同学可以用stl库开挂直接过的,而像我这种暂时不愿转c++的弱菜只好手写平衡树了。

这题用splay做的话难度不是很大,一些基本的操作就可以解决问题,但是在写代码的时候还是得需要足够的细心和耐心。值得注意的是怎样判断当前树里记录的是宠物还是主人。不难发现,树里记录的不管是宠物还是主人操作都是一样的,所以可以开一个变量记录当前树里记录的类型,当一棵树都取光时把变量重置即可。

最后删除时推荐用内存回收,还有不要忘记取余。

最后就是代码,求大神不鄙视

const
	MMOD=1000000;
	MAXN=80000;
type
	date=record
		ch:array[0..1]of longint;v,f:longint;
	end;
var
	n,i,root,top,tst,c,x,y,a,b,min,sum:longint;
	st:array[0..MAXN+10]of longint;
	t:array[0..MAXN+10]of date;
procedure newnode(var x:longint;f,k:longint);
begin
	if(tst<>0)then begin x:=st[tst];dec(tst) end
	else begin inc(top);x:=top end;
	t[x].ch[0]:=0;t[x].ch[1]:=0;t[x].v:=k;t[x].f:=f;
end;
function cmp(x,k:longint):longint;
begin
	if(t[x].ch[0]=k)then exit(0) else exit(1);
end;
procedure rotate(k,c:longint);
var i:longint;
begin
	i:=t[k].f;
	t[i].ch[c xor 1]:=t[k].ch[c];t[t[k].ch[c]].f:=i;t[k].ch[c]:=i;
	t[k].f:=t[i].f;
	if(t[i].f<>0)then t[t[i].f].ch[cmp(t[i].f,i)]:=k;
	t[i].f:=k;
end;
procedure splay(k,goal:longint);
var x,y,f1,f2:longint;
begin
	while(t[k].f<>goal)do
	begin
		x:=t[k].f;y:=t[x].f;
		if(y=goal)then rotate(k,cmp(x,k)xor 1)
		else begin
			f1:=cmp(y,x);f2:=cmp(x,k);
			if(f1=f2)then begin rotate(x,f1 xor 1);rotate(k,f1 xor 1) end
			else begin rotate(k,f2 xor 1);rotate(k,f1 xor 1) end;
		end;
	end;
	if(goal=0)then root:=k;
end;
procedure insert(k:longint);
var i,j,x:longint;
begin
	i:=root;j:=0;
	repeat
		j:=i;
		if(k<t[i].v)then i:=t[i].ch[0] else i:=t[i].ch[1];
	until i=0;
	if(k<t[j].v)then x:=0 else x:=1;
	newnode(t[j].ch[x],j,k);
	splay(t[j].ch[x],0);
end;
procedure find(k:longint);
var i:longint;
begin
	i:=root;
	repeat
		if(t[i].v<=k)then a:=i;
		if(t[i].v>=k)then b:=i;
		if(t[i].v=k)then exit;
		if(k<t[i].v)then i:=t[i].ch[0] else i:=t[i].ch[1];
	until i=0;
end;
procedure del(k:longint);
var i,j:longint;
begin
	splay(k,0);
	inc(tst);st[tst]:=k;
	if(t[k].ch[0]=0)then
	begin
		if(t[k].ch[1]=0)then
		begin
			c:=-1;root:=0;exit;
		end;
		root:=t[k].ch[1];t[t[k].ch[1]].f:=0;exit;
	end
	else begin
		i:=t[k].ch[0];j:=0;
		while(i<>0)do
		begin
			j:=i;i:=t[i].ch[1];
		end;
		splay(j,root);
		root:=t[root].ch[0];
		t[root].f:=0;t[root].ch[1]:=t[k].ch[1];t[t[k].ch[1]].f:=root;
	end;
end;
begin
	readln(n);
	c:=-1;sum:=0;top:=0;root:=0;tst:=0;
	for i:=1 to n do
	begin
		readln(x,y);
		if(c=-1)then
		begin
			c:=x;newnode(root,0,y);
		end
		else if(c=x)then insert(y)
		else if(c<>x)then
		begin
			a:=0;b:=0;min:=0;
			find(y);
			if(b=0)then min:=a;
			if(a=0)then min:=b;
			if(a<>0)and(b<>0)then
			begin
				if(abs(t[a].v-y)<=abs(t[b].v-y))then min:=a else min:=b;
			end;
			sum:=(sum+abs(t[min].v-y))mod MMOD;
			del(min);
		end;
	end;
	writeln(sum);
end.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值