BZOJ3224/LOJ104 普通平衡树 treap(树堆)
您需要写一种数据结构,来维护一些数,其中需要提供以下操作:
1. 插入x
2. 删除x(若有多个相同的数,因只删除一个)
3. 查询x的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
1.n的数据范围:n<=100000
2.每个数的数据范围:[−2e9,2e9]
题解:
二叉搜索树可以完成目标,但是单次操作的时间复杂度可能退化为线性
因此使用平衡二叉树,treap(树堆)
树堆是各类平衡树中,速度和代码复杂度比较均衡的一个
速度比splay快且好写,比sbt,替罪羊慢但简单,个人觉得代码比较简单
BZOJ
LOJ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #include <bits/stdc++.h> #define ll long long using namespace std; const int maxn=1e5+10; const int maxm=1e6+10; int casn,n,m,k; #define nd treap[now] #define ndl treap[treap[now].l] #define ndr treap[treap[now].r] #define ndt treap[tmp] struct node { int l,r,val,num,size,rnd; }treap[maxn]; int cnt,root,ans; inline void resize( int now){ nd.size=ndl.size+ndr.size+nd.num; } inline void rturn( int &now){ int tmp=nd.l; nd.l=ndt.r,ndt.r=now; ndt.size=nd.size; resize(now); now=tmp; } inline void lturn( int &now){ int tmp=nd.r; nd.r=ndt.l,ndt.l=now; ndt.size=nd.size; resize(now); now=tmp; } void insert( int &now, int val){ if (!now) { now=++cnt; nd=(node){0,0,val,1,1, rand ()}; return ; } nd.size++; if (val==nd.val)nd.num++; else if (val>nd.val){ insert(nd.r,val); if (ndr.rnd<nd.rnd) lturn(now); } else { insert(nd.l,val); if (ndl.rnd<nd.rnd) rturn(now); } } void erase( int &now, int val){ if (!now) return ; if (val==nd.val){ if (nd.num>1){ nd.num--,nd.size--; return ; } if (nd.r*nd.l==0) now=nd.l+nd.r; else { if (ndl.rnd<ndr.rnd) rturn(now); else lturn(now); erase(now,val); } } else { nd.size--; if (val>nd.val) erase(nd.r,val); else erase(nd.l,val); } } int query_rank( int now, int val){ if (!now) return 0; if (val==nd.val) return ndl.size+1; if (val>nd.val) return ndl.size+nd.num+query_rank(nd.r,val); return query_rank(nd.l,val); } int query_val( int now, int rank){ if (!now) return 0; if (rank<=ndl.size) return query_val(nd.l,rank); if (rank-ndl.size<=nd.num) return nd.val; return query_val(nd.r,rank-ndl.size-nd.num); } int query_pre( int now, int val){ if (!now) return ans; if (val<=nd.val) return query_pre(nd.l,val); ans=nd.val; return query_pre(nd.r,val); } int query_sub( int now, int val){ if (!now) return ans; if (val>=nd.val) return query_sub(nd.r,val); ans=nd.val; return query_sub(nd.l,val); } int main(){ //#define test #ifdef test freopen ( "in.txt" , "r" ,stdin); freopen ( "out.txt" , "w" ,stdout); #endif int root=0; scanf ( "%d" ,&n); for ( int i=1;i<=n;i++){ int a,b; scanf ( "%d%d" ,&a,&b); if (a==1) insert(root,b); if (a==2) erase(root,b); if (a==3) printf ( "%d\n" ,query_rank(root,b)); if (a==4) printf ( "%d\n" ,query_val(root,b)); if (a==5) printf ( "%d\n" ,query_pre(root,b)); if (a==6) printf ( "%d\n" ,query_sub(root,b)); } #ifdef test fclose (stdin); fclose (stdout); system ( "out.txt" ); #endif return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· SQL Server 内存占用高分析
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
· .NET开发智能桌面机器人:用.NET IoT库编写驱动控制两个屏幕
· 用纯.NET开发并制作一个智能桌面机器人:从.NET IoT入门开始
· 我干了两个月的大项目,开源了!
· 推荐一款非常好用的在线 SSH 管理工具
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· 千万级的大表,如何做性能调优?
· .NET周刊【1月第1期 2025-01-05】