您的位置:首页 > 其它

[PKU 2104]K-th Number(归并树)

2010-04-20 13:43 417 查看
【题目大意】:

看之前的那个题解~~

【题目分析】:

经历了ranklist倒数的悲剧事件后~~我决定学学这个归并树……

那么什么是归并树呢~

我习惯管这个东西叫线段树套数组……

开个线段树,里面就是这个区间排完序后的数列……

当然,我们不能每个节点都开,所以我们搞一个数组data[i,j],表示第i层第j个数是什么。

这个层就是线段树节点所在深度~~

然后呢,自然就是二分,然后进线段树里继续二分~然后在线段树的节点上继续二分~~

经历的悲剧的三次二分之后,我们就可以出解了~

这个东西怎么构造呢~所谓归并树,当然就要用归并排序了!!想通了吗~~其实你在归并排序的同时就已经完事了……

P.s.最开始一直是WA,后来发现开数组的时候把两个下标写反了……真悲剧,居然不爆RE~~害的我查了一下午……

【代码】(真悲剧):

program Project1;
const
inf=1000000;
type
ttype=record
left,right,deep:longint;
end;
var
a:array[0..200000] of longint;
data:array[0..20,0..200000] of longint; //就是这里,最开写的是data:array[0..200000,0..20] of longint;,哎……
tree:array[0..500000] of ttype;
n,m,i,s,t,x,y,k,mid,tmp:longint;
procedure Merge_Sort(p,deep,left,right:longint);
var
mid,k,i,j:longint;
begin
tree[p].left:=left; tree[p].right:=right; tree[p].deep:=deep;
if left=right then
begin
data[deep,left]:=a[left];
exit;
end;
mid:=(left+right) shr 1;
Merge_Sort(p shl 1,deep+1,left,mid);
Merge_Sort(p shl 1+1,deep+1,mid+1,right);
i:=left; j:=mid+1; k:=left-1;
while (i<=mid) and (j<=right) do
begin
inc(k);
if data[deep+1,i]<data[deep+1,j] then
begin
data[deep,k]:=data[deep+1,i];
inc(i);
end
else begin data[deep,k]:=data[deep+1,j]; inc(j); end;
end;
if i=mid+1 then
while j<=right do
begin
inc(k);
data[deep,k]:=data[deep+1,j];
inc(j);
end
else
while i<=mid do
begin inc(k); data[deep,k]:=data[deep+1,i]; inc(i); end;
end;
function calc(p,now:longint):longint;
var
mid,s,t:longint;
begin
s:=tree[p].left; t:=tree[p].right;
while s<t do
begin
mid:=(s+t) shr 1;
if data[tree[p].deep,mid]<now then s:=mid+1
else t:=mid;
end;
calc:=s-tree[p].left;
if data[tree[p].deep,s]<=now then inc(calc);
end;
function find(p,left,right,now:longint):longint;
var
mid:longint;
begin
if (tree[p].left=left) and (tree[p].right=right) then
exit(calc(p,now));
mid:=(tree[p].left+tree[p].right) shr 1;
if right<=mid then exit(find(p shl 1,left,right,now))
else if left>mid then exit(find(p shl 1+1,left,right,now))
else
exit(find(p shl 1,left,mid,now)+find(p shl 1+1,mid+1,right,now));
end;
begin
assign(input,'a.in');
assign(output,'a.out');
reset(input); rewrite(output);
readln(n,m);
for i:=1 to n do read(a[i]);
Merge_Sort(1,1,1,n);
for i:=1 to m do
begin
readln(x,y,k);
s:=1; t:=n;
while s<t do
begin
mid:=(s+t) shr 1;
tmp:=find(1,x,y,data[1,mid]);
if tmp<k then s:=mid+1
else t:=mid;
end;
writeln(data[1,s]);
end;
close(input); close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: