P3835-[模板]可持久化平衡树【无旋Treap】

1|0正题

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


1|1题目大意

一个空可重集,要求支持

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

但是所有操作都是基于某个历史版本

1n5×105,1|x|109


1|2解题思路

挺好写的,就是一个FHQ,可持久化部分分裂和主席树差不多,合并和线段树合并差不多。
空间记得开大点。

时空间复杂度都是O(nlogn)的。


1|3code

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=3e7+10; int n,rt[510000]; struct FHQ{ int cnt,w[N],siz[N],rnk[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 Cpy(int x,int y){ siz[x]=siz[y];rnk[x]=rnk[y];w[x]=w[y]; t[x][0]=t[y][0];t[x][1]=t[y][1];return; } void Split(int &x,int &y,int p,int k){ if(!p){x=y=0;return;} int now=++cnt;Cpy(now,p); if(w[p]<=k)x=now,Split(t[now][1],y,t[p][1],k); else y=now,Split(x,t[now][0],t[p][0],k); PushUp(now);return; } int Merge(int x,int y){ if(!x||!y)return x|y; int now=++cnt; if(rnk[x]<=rnk[y]){ Cpy(now,x); t[now][1]=Merge(t[x][1],y); } else{ Cpy(now,y); t[now][0]=Merge(x,t[y][0]); } PushUp(now);return now; } 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 &rt,int val){ int x,y; Split(x,y,rt,val); rt=Merge(Merge(x,NewNode(val)),y); return; } void Delete(int &rt,int val){ int x,y,z; Split(x,z,rt,val); Split(x,y,x,val-1); y=Merge(t[y][0],t[y][1]); rt=Merge(Merge(x,y),z); return; } int GetRank(int rt,int val){ int x,y; Split(x,y,rt,val-1); return siz[x]+1; } int GetVal(int rt,int rk) {return w[Find(rt,rk)];} int GetPre(int rt,int val){ int x,y; Split(x,y,rt,val-1); return w[Find(x,siz[x])]; } int GetNxt(int rt,int val){ int x,y; Split(x,y,rt,val); return w[Find(y,1)]; } }T; int main() { scanf("%d",&n); T.NewNode(-2147483647); T.NewNode(2147483647); rt[0]=T.Merge(1,2); for(int i=1,v,op,x;i<=n;i++){ scanf("%d%d%d",&v,&op,&x);rt[i]=rt[v]; if(op==1)T.Insert(rt[i],x); else if(op==2)T.Delete(rt[i],x); else if(op==3)printf("%d\n",T.GetRank(rt[i],x)-1); else if(op==4) printf("%d\n",T.GetVal(rt[i],x+1)); else if(op==5)printf("%d\n",T.GetPre(rt[i],x)); else if(op==6)printf("%d\n",T.GetNxt(rt[i],x)); } return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/15789051.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2021-01-11 P3507-[POI2010]GRA-The Minima Game【dp,博弈论】
2021-01-11 P3515-[POI2011]Lightning Conductor【整体二分,决策单调性】
2021-01-11 XJOI,jzoj5020-[NOI2017模拟3.17]牛奶装瓶【线段树】
2021-01-11 XJOI,jzoj5019-寻找规律【NTT,字符串hash】
2021-01-11 XJOI,jzoj5018-合并奶牛【dp,卡特兰数】
2021-01-11 P4245-[模板]任意模数多项式乘法
点击右上角即可分享
微信分享提示