平衡树

P3369 【模板】普通平衡树

https://www.luogu.org/problemnew/show/P3369

BST

 1 struct BST {
 2     int l, r; // 左右子节点在数组中的下标
 3     int val;  // 节点关键码
 4 } a[SIZE]; // 数组模拟链表
 5 int tot, root, INF = 1<<30;
 6 
 7 int New(int val) {
 8     a[++tot].val = val;
 9     return tot;
10 }
11 
12 void Build() {
13     New(-INF), New(INF);
14     root = 1, a[1].r = 2;
15 }
16 
17 int Get(int p, int val) {
18     if (p == 0) return 0; // 检索失败
19     if (val == a[p].val) return p; // 检索成功
20     return val < a[p].val ? Get(a[p].l, val) : Get(a[p].r, val);
21 }
22 
23 void Insert(int &p, int val) {
24     if (p == 0) {
25         p = New(val); // 注意p是引用,其父节点的l或r值会被同时更新
26         return;
27     }
28     if (val == a[p].val) return;
29     if (val < a[p].val) Insert(a[p].l, val);
30     else Insert(a[p].r, val);
31 }
32 
33 int GetNext(int val) {
34     int ans = 2; // a[2].val==INF
35     int p = root;
36     while (p) {
37         if (val == a[p].val) { // 检索成功
38             if (a[p].r > 0) { // 有右子树
39                 p = a[p].r;
40                 // 右子树上一直向左走
41                 while (a[p].l > 0) p = a[p].l;
42                 ans = p;
43             }
44             break;
45         }
46         // 每经过一个节点,都尝试更新后继
47         if (a[p].val > val && a[p].val < a[ans].val) ans = p;
48         p = val < a[p].val ? a[p].l : a[p].r;
49     }
50     return ans;
51 }
52 
53 void Remove(int val) {
54     // 检索val,得到节点p
55     int &p = root;
56     while (p) {
57         if (val == a[p].val) break;
58         p = val < a[p].val ? a[p].l : a[p].r;
59     }
60     if (p == 0) return;
61     if (a[p].l == 0) { // 没有左子树
62         p = a[p].r; // 右子树代替p的位置,注意p是引用
63     }
64     else if (a[p].r == 0) { // 没有右子树
65         p = a[p].l; // 左子树代替p的位置,注意p是引用
66     }
67     else { // 既有左子树又有右子树
68         // 求后继节点
69         int next = a[p].r;
70         while (a[next].l > 0) next = a[next].l;
71         // next一定没有左子树,直接删除
72         Remove(a[next].val);
73         // 令节点next代替节点p的位置
74         a[next].l = a[p].l, a[next].r = a[p].r;
75         p = next; // 注意p是引用
76     }
77 }

treap

利用随机权值维护堆的形态

  1 const int N=100010,INF=1<<30;
  2 struct treap{int l,r,c,dat,cnt,size;}a[N];
  3 int m,tot,root;
  4 
  5 int newnode(int val)
  6 {
  7     a[++tot].c=val;
  8     a[tot].dat=rand();
  9     a[tot].size=a[tot].cnt=1;
 10     return tot;
 11 }
 12 
 13 void update(int x)
 14 {
 15     a[x].size=a[a[x].l].size+a[a[x].r].size+a[x].cnt;
 16 }
 17 
 18 void build()
 19 {
 20     newnode(-INF),newnode(INF);
 21     root=1,a[1].r=2;
 22     update(root);
 23 }
 24 
 25 void zlg(int &p)//zag
 26 {
 27     int q=a[p].r;
 28     a[p].r=a[q].l,a[q].l=p,p=q;
 29     update(a[p].l),update(p);
 30 }
 31 void zrg(int &p)//zig
 32 {
 33     int q=a[p].l;
 34     a[p].l=a[q].r,a[q].r=p,p=q;
 35     update(a[p].r),update(p);
 36 }
 37 
 38 void insert(int &p,int val)
 39 {
 40     if(p==0) {p=newnode(val);return;}
 41     if(a[p].c==val) {++a[p].cnt,++a[p].size;return;}
 42     if(val<a[p].c) 
 43     {
 44         insert(a[p].l,val);
 45         if(a[p].dat<a[a[p].l].dat) zrg(p);
 46     }
 47     else
 48     {
 49         insert(a[p].r,val);
 50         if(a[p].dat<a[a[p].r].dat) zlg(p);
 51     }
 52     update(p);
 53 }
 54 
 55 int grbv(int p,int val)
 56 {
 57     if(p==0) return 0;
 58     if(a[p].c==val) return a[a[p].l].size+1;
 59     if(a[p].c>val) return grbv(a[p].l,val);
 60     return grbv(a[p].r,val)+a[a[p].l].size+a[p].cnt;
 61 }
 62 
 63 int gvbr(int p,int ran)
 64 {
 65     if(p==0) return INF;
 66     if(a[a[p].l].size>=ran) return gvbr(a[p].l,ran);
 67     else if(a[a[p].l].size+a[p].cnt>=ran) return a[p].c;
 68     else return gvbr(a[p].r,ran-a[a[p].l].size-a[p].cnt);
 69 }
 70 
 71 int getnext(int val)
 72 {
 73     int p=root,ans=2;
 74     while(p)
 75     {
 76         if(a[p].c==val)
 77         {
 78             if(a[p].r>0) 
 79             {
 80                 p=a[p].r;
 81                 while(a[p].l>0)p=a[p].l;
 82                 ans=p;
 83             }
 84             break;
 85         }
 86         if(a[p].c>val&&a[p].c<a[ans].c) ans=p;
 87         if(val<a[p].c) p=a[p].l;
 88         else p=a[p].r;
 89     }
 90     return a[ans].c;
 91 }
 92 
 93 int getlast(int val)
 94 {
 95     int p=root,ans=1;
 96     while(p)
 97     {
 98         if(a[p].c==val)//||(a[p].c>val&&a[p].l==0)
 99         {
100             if(a[p].l>0)
101             {
102                 p=a[p].l;
103                 while(a[p].r>0) p=a[p].r;
104                 ans=p;
105             } 
106             break;
107         }
108         if(a[p].c<val&&a[p].c>a[ans].c) ans=p;
109         if(val<a[p].c) p=a[p].l;
110         else p=a[p].r;
111     }
112     return a[ans].c;
113 }
114 
115 void remove(int &p,int val)
116 {
117     if(p==0) return;
118     if(a[p].c==val)
119     {
120         if(a[p].cnt>1)
121         {
122             a[p].cnt--,update(p);
123             return;
124         }
125         if(a[p].l||a[p].r)
126         {
127             if(a[p].r==0 || a[a[p].l].dat>a[a[p].r].dat)
128                 zrg(p),remove(a[p].r,val);
129             else zlg(p),remove(a[p].l,val);
130             update(p);
131         }
132         else p=0;
133         return;
134     }
135     if(val<a[p].c) remove(a[p].l,val);
136     else remove(a[p].r,val);
137     update(p);
138 }
139 
140 int main()
141 {
142     srand(time(NULL));
143     cin>>m;build();
144     FOR(i,1,m)
145     {
146         int opt,x;cin>>opt>>x;
147         switch(opt)
148         {
149             case 1:insert(root,x);break;
150             case 3:cout<<grbv(root,x)-1<<endl;break;
151             case 4:cout<<gvbr(root,x+1)<<endl;break;
152             case 5:cout<<getlast(x)<<endl;break;
153             case 6:cout<<getnext(x)<<endl;break;
154             case 2:remove(root,x);break;
155         }
156     }
157     return 0;
158 }

 

posted @ 2019-04-05 15:09  universeplayer  阅读(197)  评论(0编辑  收藏  举报