归并树是在建树的过程中保存归并排序。
归并树
以1 5 2 6 3 7为例:
把归并排序递归过程记录下来即是一棵归并树:
[1 2 3 5 6 7]
[1 2 5] [3 6 7]
[1 5] [2] [6 3] [7]
[1][5] [6][3]
用对应的下标区间建线段树:(这里下标区间对应的是原数列)
[1 6]
[1 3] [4 6]
[1 2] [3] [4 5][6]
[1][2] [4][5]
每次查找[l r]区间的第k大数时,在[1 2 3 4 5 6 7]这个有序的序列中二分所要找的数x,然后对应到线段树中去找[l r]中比x小的数有几个,即x的rank。由于线段树中任意区间对应到归并树中是有序的,所以在线段树中的某个区间查找比x小的数的个数也可以用二分在对应的归并树中找。这样一次查询的时间复杂度是log(n)^2。
要注意的是,多个x有相同的rank时,应该取最大的一个。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define ls (rt<<1) #define rs ((rt<<1)|1) #define mid ((t[rt].l+t[rt].r)>>1) const int maxn = 100500; struct node { int l , r; }t[maxn<<2]; int num[maxn] , mer[20][maxn]; int n , q; void build( int l, int r, int rt, int deep) { t[rt].l = l; t[rt].r = r; if (l == r) { mer[deep][l] = num[l]; return ; } build(l,mid,ls,deep+1); build(mid+1,r,rs,deep+1); int i=l ,j=mid+1 , p = l; /** while(p <= r) { if(i > mid || mer[deep+1][i] > mer[deep+1][j]) mer[deep][p++] = mer[deep+1][j++]; else mer[deep][p++] = mer[deep+1][i++]; } **/ while (i <= mid && j <= r) { if (mer[deep+1][i] < mer[deep+1][j]) mer[deep][p++] = mer[deep+1][i++]; else mer[deep][p++] = mer[deep+1][j++]; } while (i <= mid) mer[deep][p++] = mer[deep+1][i++]; while (j <= r) mer[deep][p++] = mer[deep+1][j++]; } int query( int l, int r, int rt, int deep, int key) { if (t[rt].r < l || t[rt].l > r) return 0; if (t[rt].l >= l && t[rt].r <= r) return lower_bound(&mer[deep][t[rt].l],&mer[deep][t[rt].r]+1,key) - &mer[deep][t[rt].l]; return query(l,r,ls,deep+1,key) + query(l,r,rs,deep+1,key); } int solve( int l, int r, int k) { int ll = 1 , rr = n , mm; while (ll < rr) { mm = (ll + rr + 1) >> 1; int tmp = query(l , r , 1 , 1 , mer[1][mm]) + 1; if (tmp <= k) ll = mm; else rr = mm - 1; } return mer[1][ll]; } int main() { while (~scanf( "%d%d" ,&n,&q)) { for ( int i=1;i<=n;i++) scanf( "%d" , &num[i]); build(1 , n , 1 , 1); int l , r , k; while (q--) { scanf( "%d%d%d" ,&l,&r,&k); int ans = solve(l , r , k); printf( "%d\n" , ans); } } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· 程序员常用高效实用工具推荐,办公效率提升利器!
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)