1. 程式人生 > >P3369-[模板]普通平衡樹【有旋Treap】

P3369-[模板]普通平衡樹【有旋Treap】

正題

評測記錄:https://www.luogu.org/recordnew/lists?uid=SSL_WYC_zombieeeeee&pid=P3369&status=&sort=0


題目大意

要求支援查詢一個數字的排名,查詢該排名的數字,插入數字,刪除數字,求前驅後繼。


解題思路

有旋Treap不解釋。


c o d e
code

#include<cstdio>
#include<algorithm>
#define INF 2147483647/3
#define N 100010
using namespace std;
int n,root;
struct Treap_node{
	int l[N],r[N];
	int val[N],dat[N];
	int cnt[N],size[N];
	int tot;
	int New(int new_val){
		val[++tot]=new_val;
dat[tot]=rand(); cnt[tot]=size[tot]=1; return tot; } void Updata(int p){ size[p]=size[l[p]]+size[r[p]]+cnt[p]; } void Build(){ New(-INF);New(INF); root=1;r[1]=2; Updata(root); } int GetRankByVal(int p,int num){ if(p==0) return 0; if(num==val[p]) return size[l[p]]+1; if(num<
val[p]) return GetRankByVal(l[p],num); return GetRankByVal(r[p],num)+size[l[p]]+cnt[p]; } int GetValByRank(int p,int rank){ if (p==0) return INF; if(size[l[p]]>=rank) return GetValByRank(l[p],rank); if(size[l[p]]+cnt[p]>=rank) return val[p]; return GetValByRank(r[p],rank-size[l[p]]-cnt[p]); } void zig(int &p){ int q=l[p]; l[p]=r[q];r[q]=p;p=q; Updata(r[p]);Updata(p); } void zag(int &p){ int q=r[p]; r[p]=l[q];l[q]=p;p=q; Updata(l[p]);Updata(p); } void Insert(int &p,int num){ if(p==0){ p=New(num); return; } if(num==val[p]){ cnt[p]++;Updata(p); return; } if(num<val[p]){ Insert(l[p],num); if(dat[p]<dat[l[p]]) zig(p); } else{ Insert(r[p],num); if(dat[p]<dat[r[p]]) zag(p); } Updata(p); } int GetPre(int num){ int ans=1; int p=root; while(p){ if(num==val[p]){ if(l[p]>0){ p=l[p]; while(r[p]>0) p=r[p]; ans=p; } break; } if(val[p]<num&&val[p]>val[ans]) ans=p; p=num<val[p]?l[p]:r[p]; } return val[ans]; } int GetNext(int num){ int ans=2; int p=root; while(p){ if(num==val[p]){ if(r[p]>0){ p=r[p]; while(l[p]>0) p=l[p]; ans=p; } break; } if(val[p]>num&&val[p]<val[ans]) ans=p; p=num<val[p]?l[p]:r[p]; } return val[ans]; } void Remove(int &p,int num){ if(p==0) return; if(num==val[p]){ if(cnt[p]>1){ cnt[p]--;Updata(p); return; } if(l[p]||r[p]){ if(r[p]==0||dat[l[p]]>dat[r[p]]) zig(p),Remove(r[p],num); else zag(p),Remove(l[p],num); Updata(p); } else p=0; return; } num<val[p]?Remove(l[p],num):Remove(r[p],num); Updata(p); } }a; int main() { a.Build(); scanf("%d",&n); while(n--){ int opt,x; scanf("%d%d",&opt,&x); switch(opt){ case 1: a.Insert(root,x); break; case 2: a.Remove(root,x); break; case 3: printf("%d\n",a.GetRankByVal(root,x)-1); break; case 4: printf("%d\n",a.GetValByRank(root,x+1)); break; case 5: printf("%d\n",a.GetPre(x)); break; case 6: printf("%d\n",a.GetNext(x)); break; } } }