[PKU 2104]K-th Number(归并树)
2010-04-20 13:43
417 查看
【题目大意】:
看之前的那个题解~~
【题目分析】:
经历了ranklist倒数的悲剧事件后~~我决定学学这个归并树……
那么什么是归并树呢~
我习惯管这个东西叫线段树套数组……
开个线段树,里面就是这个区间排完序后的数列……
当然,我们不能每个节点都开,所以我们搞一个数组data[i,j],表示第i层第j个数是什么。
这个层就是线段树节点所在深度~~
然后呢,自然就是二分,然后进线段树里继续二分~然后在线段树的节点上继续二分~~
经历的悲剧的三次二分之后,我们就可以出解了~
这个东西怎么构造呢~所谓归并树,当然就要用归并排序了!!想通了吗~~其实你在归并排序的同时就已经完事了……
P.s.最开始一直是WA,后来发现开数组的时候把两个下标写反了……真悲剧,居然不爆RE~~害的我查了一下午……
【代码】(真悲剧):
看之前的那个题解~~
【题目分析】:
经历了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.
相关文章推荐
- pku 2104 -- K-th Number (sort +小优化水过)
- POJ 2104 K-th Number 归并树
- PKU-2104-K-th Number
- PKU_2104_归并树(线段树)
- POJ2104_K-th Number_归并树|二分 ||平方分割的分桶法|二分
- POJ2104 K-th Number——划分树——pku2104
- POJ 2104 K-th Number(区间第k大数)(平方分割,归并树,划分树)
- 【转】pku 2104 K-th Number 求某区间第k小数 归并排序+线段树
- 【 POJ - 2104】K-th Number 【归并树】
- POJ 2104 K-th Number(区间第k大数)(平方切割,归并树,划分树)
- PKU 2104 K-th Number
- PKU 2104(线段树+归并+二分)
- PKU-2104-K-th Number
- 归并树(POJ 2104 K-th Number)
- poj 2104 K-th Number 归并树
- [PKU 2104]K-th Number(树套树版)
- POJ 2104 K-th Number 归并树与划分树
- Pku2104 k - th number
- pku2104 K-th Number
- POJ-2104 K-th Number(线段树[归并树]-区间第k大)