日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【BZOJ - 3224】普通平衡树(Splay模板题)

發布時間:2023/12/10 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【BZOJ - 3224】普通平衡树(Splay模板题) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題干:

您需要寫一種數據結構(可參考題目標題),來維護一些數,其中需要提供以下操作:
1. 插入x數
2. 刪除x數(若有多個相同的數,因只刪除一個)
3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名)
4. 查詢排名為x的數
5. 求x的前驅(前驅定義為小于x,且最大的數)
6. 求x的后繼(后繼定義為大于x,且最小的數)

Input

第一行為n,表示操作的個數,下面n行每行有兩個數opt和x,opt表示操作的序號(1<=opt<=6)

Output

對于操作3,4,5,6每行輸出一個數,表示對應答案

Sample Input

10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598

Sample Output

106465 84185 492737

Hint

1.n的數據范圍:n<=100000

2.每個數的數據范圍:[-2e9,2e9]

解題報告:

Splay的大模板題。

AC代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX =100007;//= 2e5 + 5; int fa[MAX],cnt[MAX],tr[MAX][2],size[MAX],val[MAX],tot,root; inline bool get(int x) {return tr[fa[x]][1]==x; } inline void clear(int x) {fa[x]=cnt[x]=tr[x][0]=tr[x][1]=size[x]=val[x]=0; } inline void pushup(int x) {//更新x節點的信息 if(x == 0) return;//其實不加也行,因為不會去維護根節點的父節點的關系。size[x] = cnt[x]; // if(tr[x][0]) size[x] += size[tr[x][0]] ; // if(tr[x][1]) size[x] += size[tr[x][1]] ;沒啥用、、size[x] += size[tr[x][0]] + size[tr[x][1]]; } inline void rotate(int x) {//以下注釋默認我是我爸的左兒子 int old = fa[x],oldf = fa[old],w=get(x),ww=get(old);//修改我爸和我右兒子的關系 tr[old][w] = tr[x][w^1]; fa[tr[old][w]]=old;//修改我和我爸的關系 tr[x][w^1] = old;fa[old] = x;//修改我和我爺爺的關系 fa[x] = oldf;if(oldf) tr[oldf][ww] = x;pushup(old);pushup(x); } inline void splay(int x) {for(int old=fa[x]; old = fa[x]; rotate(x)) {//默認根節點是0的情況下才可以這么用判斷條件 if(fa[old]) {rotate(get(x) == get(old) ? old : x);}}root = x; } inline void insert(int x) {//x為權值 if(root == 0) {val[++tot] = x;root=tot;cnt[tot]=size[tot]=1;fa[tot] = tr[tot][0]=tr[tot][1]=0;return; }int cur = root,old = 0;while(1) {if(x == val[cur]) {cnt[cur]++;pushup(cur);pushup(old);splay(cur);return;}old = cur;cur = tr[cur][val[cur] < x];if(cur == 0) {val[++tot] = x;fa[tot] = old; tr[tot][0]=tr[tot][1]=0; tr[old][x>val[old]] = tot;//維護父節點和孩子節點 cnt[tot] = size[tot] = 1;pushup(old); splay(tot);return;}} } inline int pre(int x) {int cur = root,old=0;while(cur) {if(val[cur] < x) old = cur,cur = tr[cur][1];else cur = tr[cur][0]; }return old; } inline int nxt(int x) {int cur = root,old = 0;while(cur) {if(val[cur] > x) old = cur,cur = tr[cur][0];else cur = tr[cur][1];}return old; } //inline int pre() { // int cur = tr[root][0]; // while(tr[cur][1]) cur = tr[cur][1]; // return cur; //} //inline int nxt() { // int cur = tr[root][1]; // while(tr[cur][0]) cur = tr[cur][0]; // return cur; //}inline int Rank(int x) {//查詢x的Rank int cur = root,res = 0;while(1) { // if(cur == 0) return -1;//說明數據非法 if(x < val[cur]) cur = tr[cur][0];else {res += size[tr[cur][0]];if(x == val[cur]) {splay(cur); return res+1;}//此時x和樹中的點重合,樹中不允許有兩個相同的點res += cnt[cur]; cur = tr[cur][1];}} } inline int kth(int x) {//查詢排名為x的數的val int cur = root;while(1) {if(tr[cur][0] && x <= size[tr[cur][0]]) cur = tr[cur][0];else {int tmp = size[tr[cur][0]] + cnt[cur];if(x <= tmp) {splay(cur);return val[cur];}x -= tmp;cur = tr[cur][1];}} } inline void del(int x) {Rank(x);//找到x的排名并把它旋轉上來if(cnt[root] > 1) {cnt[root]--;return;}if(!tr[root][0] && !tr[root][1]) root=0;//可加個clear();函數else if(!tr[root][0]) {root = tr[root][1];fa[root]=0;} //pushup(root);else if(!tr[root][1]) {root = tr[root][0];fa[root]=0;}//pushup(root);else {int leftbig = tr[root][0],oldrt=root;while(tr[leftbig][1]) leftbig = tr[leftbig][1];splay(leftbig);tr[root][1]=tr[oldrt][1];fa[tr[oldrt][1]]=root;pushup(root);} } //全程表示根節點不是0,但是根節點的父節點,我們認為是0 (fa[rt]==0) int main() {int n;cin>>n;for(int i = 1; i<=n; i++) {int op,x;scanf("%d%d",&op,&x);if(op == 1) insert(x);if(op == 2) del(x);if(op == 3) printf("%d\n",Rank(x));if(op == 4) printf("%d\n",kth(x));if(op == 5) printf("%d\n",val[pre(x)]);if(op == 6) printf("%d\n",val[nxt(x)]);}return 0 ; }

總結:嗚嗚嗚好難寫、、、

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的【BZOJ - 3224】普通平衡树(Splay模板题)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。