1. 程式人生 > >【模板】普通平衡樹 Treap

【模板】普通平衡樹 Treap

題目描述

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

輸入輸出格式

輸入格式:
第一行為n,表示操作的個數,下面n行每行有兩個數opt和x,opt表示操作的序號( 1≤opt≤6 )

輸出格式:
對於操作3,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
說明

時空限制:1000ms,128M

1.n的資料範圍: n≤100000
2.每個數的資料範圍: [-{10}^7, {10}^7]

卡了我一星期的資料結構,今天終於A了一題,感覺可以歡呼一下。。。
大概有以下幾個錯誤:
1.忘記判斷 o == NULL
2.cmp搞錯(就是這東西特別難查)
3.忘記更新子節點個數

下面是風格越發奇怪的程式碼(大多數是大白書上學來的)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std; const int N=100010,inf=10000010; int n; struct node { node* ch[2]; int r,s,v; node(int v):v(v){s=1; r=rand(); ch[0]=ch[1]=NULL;} bool operator < (const node& rhs) const {return r < rhs.r;} int cmp(int x) { if(x == v)return -1; return x < v ? 0
: 1 ; } void maintain(){ s=1; if(ch[0] != NULL) s+=ch[0]->s; if(ch[1] != NULL) s+=ch[1]->s; } }; node* rt=NULL; void rotate(node* &o,int d) { node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o->maintain();k->maintain(); o=k; } void ins(node* &o,int x) { if(o == NULL){o=new node(x);return ;} int d=(x < o->v ? 0 : 1);ins(o->ch[d],x); if(o->ch[d] > o) rotate(o,d^1); o->maintain(); } void del(node* &o,int x) { if(o == NULL) return ; int d=o->cmp(x); if(d == -1) { if(o->ch[0] != NULL && o->ch[1] != NULL) { int d2=(o->ch[1]->r > o->ch[0]->r ? 0 : 1); rotate(o,d2);del(o->ch[d2],x); } else {if(o->ch[0] == NULL) o=o->ch[1];else o=o->ch[0];} } else del(o->ch[d],x); if(o != NULL) o->maintain(); } int kth(node *o,int k) { if(o == NULL || k > o->s || o <= 0) return 0; int s=(o->ch[0] == NULL ? 0 : o->ch[0]->s); if(k == s+1) return o->v; if(k <= s) return kth(o->ch[0], k); return kth(o->ch[1], k-s-1); } void rank(node *o,int x,int &ans,int k) { if(o==NULL) return ; int ss=(o->ch[0] == NULL ? 0 : o->ch[0]->s); if(o->v < x) { rank(o->ch[1],x,ans,k+ss+1); return ; } if(o->v == x) ans=min(ans,k+ss+1); rank(o->ch[0],x,ans,k); } void pre(node* o,int x,int &ans) { if(o == NULL) return ; if(o->v < x) { ans=max(o->v, ans); pre(o->ch[1],x,ans); return ; } pre(o->ch[0],x,ans); } void post(node* o,int x,int &ans) { if(o == NULL) return ; if(o->v > x) { ans=min(o->v, ans); post(o->ch[0], x, ans); return ; } post(o->ch[1], x, ans); } int read() { int out=0, f=1; char c=getchar(); while(c < '0' || c> '9') {if(c == '-') f=-1; c=getchar();} while(c >= '0' && c <= '9'){ out=(out<<1)+(out<<3)+c-'0'; c=getchar(); } return out*f; } void solve() { n=read(); while(n--) { int opt=read(),x=read(); if(opt == 1) ins(rt, x); if(opt == 2) del(rt, x); if(opt == 4) printf("%d\n",kth(rt, x)); if(opt == 3) { int ans3=inf; rank(rt, x,ans3,0); printf("%d\n",ans3); } if(opt == 5) { int ans5=0-inf; pre(rt, x,ans5); printf("%d\n",ans5); } if(opt == 6) { int ans6=inf; post(rt, x,ans6); printf("%d\n",ans6); } } } int main() { solve(); return 0; }