P3369-[模板]普通平衡树【无旋Treap】

1|0正题

题目链接:https://www.luogu.com.cn/problem/P3369


1|1题目大意

一个空可重集,要求支持

  • 插入一个数x
  • 删除一个数x
  • 询问一个数x的排名
  • 询问排名第x的数字
  • 询问x的前驱
  • 询问x的后继

1n105,1|x|107


1|2解题思路

拖了两年的FHQ终于还是写了(还有二逼平衡树拖到现在还没写)。

看的是别人博客学的:https://www.luogu.com.cn/blog/85514/fhq-treap-xue-xi-bi-ji

具体特点就是结构固定我通过分裂的方式直接让节点插入在对应的位置,这样就不需要旋转来调整结构了。

还有相同的数字不是存在同一个节点而是分开存的,所以同一个数字可以有多个节点。

时间复杂度:O(nlogn)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+10; int T,root; struct FHQ{ int cnt,w[N],rnk[N],siz[N],t[N][2]; int NewNode(int val){ w[++cnt]=val;siz[cnt]=1; rnk[cnt]=rand(); return cnt; } void PushUp(int x){ siz[x]=siz[t[x][0]]+siz[t[x][1]]+1; return; } void Split(int &x,int &y,int p,int val){ if(!p){x=y=0;return;} if(w[p]<=val)x=p,Split(t[x][1],y,t[p][1],val); else y=p,Split(x,t[y][0],t[p][0],val); PushUp(p);return; } int Merge(int x,int y){ if(!x||!y)return x|y; if(rnk[x]<rnk[y]){ t[x][1]=Merge(t[x][1],y); PushUp(x);return x; } else{ t[y][0]=Merge(x,t[y][0]); PushUp(y);return y; } } int Find(int x,int k){ if(siz[t[x][0]]>=k)return Find(t[x][0],k); if(siz[t[x][0]]+1==k)return x; return Find(t[x][1],k-siz[t[x][0]]-1); } void Insert(int w){ int x,y;Split(x,y,root,w); root=Merge(Merge(x,NewNode(w)),y); } void Delete(int w){ int x,y,z; Split(x,y,root,w-1); Split(y,z,y,w); y=Merge(t[y][0],t[y][1]); root=Merge(Merge(x,y),z); return; } int GetRank(int w){ int x,y,ans; Split(x,y,root,w-1); ans=siz[x]+1; root=Merge(x,y); return ans; } int GetVal(int r) {return w[Find(root,r)];} int GetPre(int r){ int x,y,ans; Split(x,y,root,r-1); ans=w[Find(x,siz[x])]; root=Merge(x,y); return ans; } int GetNxt(int r){ int x,y,ans; Split(x,y,root,r); ans=w[Find(y,1)]; root=Merge(x,y); return ans; } }Tr; int main() { scanf("%d",&T); Tr.NewNode(-1e9);Tr.NewNode(1e9); root=Tr.Merge(1,2); while(T--){ int op,w; scanf("%d%d",&op,&w); if(op==1)Tr.Insert(w); else if(op==2)Tr.Delete(w); else if(op==3)printf("%d\n",Tr.GetRank(w)-1); else if(op==4)printf("%d\n",Tr.GetVal(w+1)); else if(op==5)printf("%d\n",Tr.GetPre(w)); else if(op==6)printf("%d\n",Tr.GetNxt(w)); } }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/15781814.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2021-01-09 P4173-残缺的字符串【FFT】
2021-01-09 P3649-[APIO2014]回文串【PAM】
2021-01-09 XJOI,jzoj5527-[清华冬令营2018模拟]Silly【欧拉函数,Pollard-Rho】
点击右上角即可分享
微信分享提示