划分树

邪恶的东西……思想简单,实现巨复杂……搞了好久才看懂标程

问题:考虑一个静态问题,给出一个数组,每次询问任意区间【l,r】内的第k小值,设计一个离线算法

Code:

Program HFS;

var
	a,sort		:		array[1..10000] of longint;
	s,z			:		array[1..10,1..100000] of longint;
	n,m,x,y,k	:		longint;
	i			:		longint;
	
	Procedure Qsort(l,r:longint);
	var	
		i,j,t,m	:		longint;
	begin
		i:=l ; j:=r; m:=a[(l+r)	shr 1];
		repeat
			while a[i]<m do inc(i);
			while a[j]>m do dec(j);
			if i<=j then
				begin
					t:=a[i]; a[i]:=a[j]; a[j]:=t;
					t:=sort[i]; sort[i]:=sort[j]; sort[j]:=t; 
					inc(i); dec(j);
				end;
		until i>j;
		if i<r then Qsort(i,r);
		if l<j then Qsort(l,j);
	end;
	
	Procedure	Build(h,l,r:longint);
	var	
		i,mid,p		:		longint;
	begin
		mid:=(l+r) shr 1+1; p:=0;
		for i:=l to r do	
			if z[h,i]<mid then	
				begin
					z[h+1,l+p]:=z[h,i];
					inc(p);
					s[h,i]:=p;
				end else
				begin	
					z[h+1,mid+i-p-l]:=z[h,i];
					s[h,i]:=p;
				end;
		if p>1 then Build(h+1,l,mid-1);
		if mid<r then Build(h+1,mid,r);
	end;
	
	Function find(h,st,et,l,r,k:longint):longint;
	var	
		beg,ed,mid	:	longint;
	begin
		if st=et then 	exit(z[h,st]);
		mid:=(st+et) shr 1+1;
		if st=l then beg:=0 else beg:=s[h,l-1];
		ed:=s[h,r];
		if ed-beg>=k then
			exit(find(h+1,st,mid-1,st+beg,st+ed-1,k)) else
			exit(find(h+1,mid,et,mid+l-st-beg,mid+r-st-ed,k-(ed-beg)));
	end;
	
begin
	assign(input,'HFS.in');
	assign(output,'HFS.out');
	reset(input); rewrite(output);
	readln(n,m);
	for i:=1 to n do 
		begin
			read(a[i]);
			sort[i]:=i;
		end;
	readln;
	Qsort(1,n);
	for i:=1 to n do z[1,sort[i]]:=i;
	Build(1,1,n);
	for i:=1 to m do 
		begin
			readln(x,y,k);
			writeln(a[sort[find(1,1,n,x,y,k)]]);
		end;
	close(input); close(output);
end.

posted on 2012-02-22 23:00  爱宝宝  阅读(317)  评论(0编辑  收藏  举报

导航