1. 程式人生 > >[模板]平衡樹splay

[模板]平衡樹splay

氣死我了,調了一個下午+兩節課,各種大大小小的錯誤,各種調QAQ,最後總之是調出來了.

其實就是一個雙旋操作,然後其他就是左兒子<當前節點<右兒子,剩下就是細節了.

題幹:

題目描述

您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作:

    插入xxx數
    刪除xxx數(若有多個相同的數,因只刪除一個)
    查詢xxx數的排名(排名定義為比當前數小的數的個數+1+1+1。若有多個相同的數,因輸出最小的排名)
    查詢排名為xxx的數
    求xxx的前驅(前驅定義為小於xxx,且最大的數)
    求xxx的後繼(後繼定義為大於xxx,且最小的數)

輸入輸出格式
輸入格式:

第一行為nnn,表示操作的個數,下面nnn行每行有兩個數optoptopt和xxx,optoptopt表示操作的序號( 
1≤opt≤6 1 \leq opt \leq 6 1≤opt≤6 ) 輸出格式: 對於操作3,4,5,63,4,5,63,4,5,6每行輸出一個數,表示對應答案 輸入輸出樣例 輸入樣例#1: 複製 10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598 輸出樣例#1: 複製 106465 84185 492737

 

程式碼:

#include<iostream>
#include<cstdio>
#include
<cmath> #include<queue> #include<algorithm> #include<vector> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) #define pr pair<int,int> #define
mp make_pair const int INF = 2147480000; const double eps = 1e-8; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } struct node { int v,fa,ch[3],sum,recy; }e[500005]; int n,points,N; #define root e[0].ch[1] void update(int x) { e[x].sum = e[e[x].ch[0]].sum + e[e[x].ch[1]].sum + e[x].recy; } int iden(int x) { return e[e[x].fa].ch[0] == x ? 0 : 1; } void connect(int x,int f,int son) { e[x].fa = f; e[f].ch[son] = x; } void rotate(int x) { int y = e[x].fa; int mroot = e[y].fa; int mrootson = iden(y); int yson = iden(x); int b = e[x].ch[yson ^ 1]; connect(b,y,yson); connect(y,x,yson ^ 1); connect(x,mroot,mrootson); update(y); update(x); } void splay(int at,int to) { to = e[to].fa; while(e[at].fa != to) { int up = e[at].fa; if(e[up].fa == to) rotate(at); else if(iden(up) == iden(at)) { rotate(up); rotate(at); } else { rotate(at); rotate(at); } } } int crepoint(int v,int fa) { n++; e[n].v = v; e[n].fa = fa; // cout<<v<<" "<<fa<<endl; e[n].sum = e[n].recy = 1; return n; } void destroy(int x) { e[x].v = e[x].ch[0] = e[x].ch[1] = e[x].sum = e[x].fa = e[x].recy = 0; if(x == n) n--; while(e[n].v == 0 && e[n].sum == 0 && n > 0) n--; } int find(int v) { int now = root; while(true) { if(e[now].v == v) { splay(now,root); return now; } int nxt = v < e[now].v ? 0 : 1; if(!e[now].ch[nxt]) return 0; now = e[now].ch[nxt]; } } int build(int v) { points++; // cout<<v<<endl; if(n == 0) { root = 1; crepoint(v,0); } else { int now = root; while(true) { // cout<<now<<endl; e[now].sum++; if(v == e[now].v) { e[now].recy++; return now; } int nxt = v < e[now].v ? 0 : 1; if(!e[now].ch[nxt]) { crepoint(v,now); e[now].ch[nxt] = n; return n; } now = e[now].ch[nxt]; } } return 0; } void push(int v) { int add = build(v); if( rand() % 20 == 1 ) splay(add,root); } void pop(int v) { int deal = find(v); if(!deal) return; points--; if(e[deal].recy > 1) { e[deal].recy--; e[deal].sum--; return; } if(!e[deal].ch[0]) { root = e[deal].ch[1]; e[root].fa = 0; } else { int lef = e[deal].ch[0]; while(e[lef].ch[1]) lef = e[lef].ch[1]; splay(lef,e[deal].ch[0]); int rig = e[deal].ch[1]; connect(rig,lef,1);connect(lef,0,1); update(lef); } destroy(deal); } int Rank(int v) { int ans = 0,now = root; // cout<<v<<endl; while(true) { if(e[now].v == v) return ans + e[e[now].ch[0]].sum + 1; if(now == 0) return 0; if(v < e[now].v) now = e[now].ch[0]; else { ans = ans + e[e[now].ch[0]].sum + e[now].recy; now = e[now].ch[1]; } } //if(now) splay(now,root); return 0; } int atRank(int x) { if(x > points) return -INF; int now = root; // cout<<root<<endl; while(true) { // cout<<now<<endl; int minused = e[now].sum - e[e[now].ch[1]].sum; if(x > e[e[now].ch[0]].sum && x <= minused) break; if(x < minused) now = e[now].ch[0]; else { x = x - minused; now = e[now].ch[1]; } } //splay(now,root); return e[now].v; } int upper(int v) { int now = root; int result = INF; while(now) { if(e[now].v > v && e[now].v < result) result = e[now].v; if(v < e[now].v) now = e[now].ch[0]; else now = e[now].ch[1]; } return result; } int lower(int v) { int now = root; int result = -INF; while(now) { // cout<<now<<endl; if(e[now].v < v && e[now].v > result) result = e[now].v; if(v > e[now].v) now = e[now].ch[1]; else now = e[now].ch[0]; } return result; } void Szcheck( int pos ){ if( e[pos].ch[0] ) Szcheck(e[pos].ch[0]); if( e[pos].ch[1] ) Szcheck(e[pos].ch[1]); if( e[e[pos].ch[0]].sum + 1 + e[e[pos].ch[1]].sum != e[pos].sum ){ cout << "Size Error At Pos" << pos << endl; } } void gg() { cout<<n<<endl; duke(i,1,n) { printf("%d ",e[i].v); } puts(""); } int main() { // freopen("3369.in","r",stdin); read(N); duke(i,1,N) { int opt,value; // cout<<endl<<i<<endl; read(opt);read(value); // if(opt != 1 && opt != 2) // cout<<opt<<" "<<value<<endl; switch(opt) { case 1 : push(value);break; case 2 : pop(value);break; case 3 : cout<<Rank(value)<<endl;break; case 4 : {cout<<atRank(value)<<endl;}break; case 5 : cout<<lower(value)<<endl;break; case 6 : cout<<upper(value)<<endl;break; case 7 : gg(); } //Szcheck(root); // cout<<i<<endl; } return 0; } /* 10 1 106465 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598 4 1 */

程式碼有點長...