Rq-350【归并树】
来源:互联网 发布:淘宝店铺欢迎语幽默 编辑:程序博客网 时间:2024/04/29 15:01
题目:找第k小的数
问题编号:350
题目描述给出一个长度为N的序列A1,A2,A3,...,AN,其中每项都是
小于10^5的自然数。
现在有M个询问,每个询问都是Ai...Aj中第k小的数等
于多少。
数据范围:
在60%的数据中,1≤N≤1000,1≤M≤1000
在100%的数据中,1≤N≤10000,1≤M≤2000
Darkmaster说:“这题水吧?水了就得给我AC了看看,呵呵!”
输入格式
第一行两个正整数N,M。
第二行N个数,表示序列A1,A2,...,AN。
紧着的M行,每行三个正整数i,j,k(k≤j-i+1),表示
询问Ai...Aj中第k小的数等于多少。
输出格式
共输出M行,第i行输出第i个询问的答案。
==================================================================
按题目给的数据规模,目测记下元素下标跑个快排然后朴素(O(nm+nlog2n))就能过,但作者显然不是这个意思,求区间kth数有一类现成的数据结构。
比如这题,我们可以归并树,其基本思想就是用log2n层的检索,记下归并排序的过程,每次查找区间[l,r]的kth数时,设x=kth,我们可以算出x在区间[l,r]的排名,然后二分枚举即可;至于怎么求x在[l,r]内的排名,可以将[l,r]拆解为若干个子区间(子区间存在于归并的过程中),将每个子区间内小于x的元素数量累加起来即可;至于怎么在子区间内累加,由于子区间是有序的,再来一次二分就可以了。
综上,归并树的空间复杂度为 nlog2n ,时间复杂度为 (log2n)^3。
如果用归并树来实现这一问题的话,当数据规模n<=10^6时可以在1s内出解。
==================================================================
先贴个代码:
varg:array[1..20,1..10000] of longint;a:array[1..10000] of longint;n,m:longint;procedure fsetup(x,l,r:longint);var mid,i,j,k:longint;begin if l=r then g[x,l]:=a[l] else begin mid:=(l+r)shr 1; fsetup(x+1,l,mid); fsetup(x+1,mid+1,r); j:=l; k:=mid+1; for i:=l to r do if (k<=r)and((j>mid)or(g[x+1,k]<g[x+1,j])) then begin g[x,i]:=g[x+1,k]; inc(k); end else begin g[x,i]:=g[x+1,j]; inc(j); end; end;end;function xth(x,l,r,v:longint):longint;var mid:longint;begin if l>r then exit(0); mid:=(l+r)shr 1; if g[x,mid]<v then xth:=mid-l+1+xth(x,mid+1,r,v) else xth:=xth(x,l,mid-1,v)end;function th(x,ll,rr,l,r,v:longint):longint;var mid:longint;begin if (ll=l)and(rr=r)then exit(xth(x,l,r,v)) else begin mid:=(ll+rr)shr 1; if r<=mid then exit(th(x+1,ll,mid,l,r,v)); if l>mid then exit(th(x+1,mid+1,rr,l,r,v)); exit(th(x+1,ll,mid,l,mid,v)+th(x+1,mid+1,rr,mid+1,r,v)); end;end;function query(l,r,k:longint):longint;var low,high,mid:longint;begin low:=0; high:=100000; while low<high do begin mid:=((low+high)shr 1)+1; if th(1,1,n,l,r,mid)<k then low:=mid else high:=mid-1; end; exit(low);end;procedure main;var i,p,q,r:longint;begin readln(n,m); for i:=1 to n do read(a[i]); readln; fsetup(1,1,n); for i:=1 to m do begin readln(p,q,r); writeln(query(p,q,r)); end;end;begin main;end.==================================================================
应当指出,由于题目限定了元素的取值范围是非负的,所以在对x的二分上直接采用了shr,而在另外一道类似题目上(数据取值范围是-Inf~Inf),笔者采取同样的方式处理结果挂的很惨(把符号位直接挪了过来~囧)。
其实还有一种和归并树很相似的数据结构-划分树,这个等我A掉另外那道题再说吧!
- Rq-350【归并树】
- rq
- rq-104
- rq-481
- QR,RQ分解
- Python - rq / mrq / Celery
- 【矩阵】RQ/QR 分解
- 归并树
- 归并树
- 归并树
- CFS调度的总结 - (单rq vs 多rq)
- Rq图结构水题~
- 调度_全局RQ算法
- django rq cron 定时任务
- poj 2104 归并树
- 归并排序-败者树
- 生成最优归并树
- POJ2104 归并树
- 如何用C语言清空特定文件夹中的所有文件
- 黑马程序员——前几天的总结
- 分享来自zoomla!逐浪CMS的三个ASP.NET实用技巧
- Linux安装包制作
- 用MPMoviePlayerController做在线音乐播放
- Rq-350【归并树】
- 黑马程序员_面向对象三大特性
- cvFillPoly
- gdbserver: linux-x86-low.c error: sys/reg.h: No such file or directory
- 职场人生(五):思考缺席九期作品演习
- 设计模式(一)工厂模式Factory(创建型)
- hdu 1253 胜利大逃亡 BFS
- object-->string-->long
- hdu 1016 Prime Ring Problem(DFS +回溯法)