1. 程式人生 > >【bzoj 3224】Tyvj 1728 普通平衡樹

【bzoj 3224】Tyvj 1728 普通平衡樹

Tyvj 1728 普通平衡樹

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 11767 Solved: 5021
[Submit][Status][Discuss]
Description

您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作:
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]
Source

平衡樹

[Submit][Status][Discuss]
複習下treap

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100065;
int l[maxn],r[maxn],v[maxn],rnd[maxn],w[maxn],sz[maxn];
int n,cnt,root,ans;
void pushUp(int rt)
{
    sz[rt]=sz[l[rt]]+sz[r[rt]]+w[rt];
}
void rturn(int &k)
{
    int t=l[k];l[k]=r[t];r[t]=k;
    sz[t]=sz[k];pushUp(k);k=t;
}
void
lturn(int &k) { int t=r[k];r[k]=l[t];l[t]=k; sz[t]=sz[k];pushUp(k);k=t; } void ins(int &k,int x) { if(k==0){ k=++cnt;sz[k]=w[k]=1;v[k]=x;rnd[k]=rand();return; } sz[k]++; if(v[k]==x)w[k]++; else if(x>v[k]){ ins(r[k],x); if(rnd[r[k]] < rnd[k])lturn(k); } else{ ins(l[k],x); if(rnd[l[x]] < rnd[k])rturn(k); } } void del(int &k,int x){ if(k==0)return; if(v[k]==x){ if(w[k]>1){ w[k]--;sz[k]--;return; } if(l[k]*r[k]==0)k=l[k]+r[k]; else if(rnd[l[k]] < rnd[r[k]]){ rturn(k);del(k,x); } else lturn(k),del(k,x); } else if(x>v[k]) sz[k]--,del(r[k],x); else sz[k]--,del(l[k],x); } int rank(int k,int x) { if(!k)return k; if(v[k]==x)return sz[l[k]]+1; else if(x>v[k]) return rank(r[k],x)+sz[l[k]]+w[k]; else return rank(l[k],x); } int kth(int k,int x) { if(!k)return k; if(x<=sz[l[k]]) return kth(l[k],x); else if(x>sz[l[k]]+w[k]) return kth(r[k],x-sz[l[k]]-w[k]); else return v[k]; } void pro(int k,int x) { if(!k)return; if(v[k]<x){ ans=k;pro(r[k],x); } else pro(l[k],x); } void afs(int k,int x) { if(!k)return; if(v[k]>x){ ans=k;afs(l[k],x); } else afs(r[k],x); } int main() { scanf("%d",&n); int opt,x; for(int i=1;i<=n;i++){ scanf("%d %d",&opt,&x); switch(opt) { case 1:ins(root,x);break; case 2:del(root,x);break; case 3:printf("%d\n",rank(root,x));break; case 4:printf("%d\n",kth(root,x));break; case 5:ans=0;pro(root,x);printf("%d\n",v[ans]);break; case 6:ans=0;afs(root,x);printf("%d\n",v[ans]);break; } } return 0; }