首页 > 代码库 > Noi2004郁闷的出纳员-treap树

Noi2004郁闷的出纳员-treap树

 treap树只需要单旋,可以写在一个函数中。
当需要删除某点时只需不断将这个点下旋知道它只有少于一个的儿子,让他的 儿子 或者 空 取代它。
插入时先插入,然后从底下向上通过旋转维护堆的性质。
下面附标程:

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 struct Node{
 7        int ch[2];
 8        int key,size,pri;
 9        void set(int x){ch[0]=ch[1]=0;key=x;size=1;pri=rand();}
10 }tree[1000000];
11 int tree_size,root,sum,all;
12 int n,minn;
13 void update(int v){
14      tree[v].size=1;
15      if(tree[v].ch[0]) tree[v].size+=tree[tree[v].ch[0]].size;
16      if(tree[v].ch[1]) tree[v].size+=tree[tree[v].ch[1]].size;
17 }
18 void rotate(int &v,int f){
19      int y=tree[v].ch[f];
20      tree[v].ch[f]=tree[y].ch[!f];
21      tree[y].ch[!f]=v;
22      update(v);update(y);
23      v=y;
24 }   
25 void insert(int &v,int x){
26      if(v==0){tree[v=++sum].set(x);}
27      else{
28           tree[v].size++;
29           int f=!(x<=tree[v].key);
30           insert(tree[v].ch[f],x); 
31           if(tree[v].pri<tree[tree[v].ch[f]].pri) rotate(v,f);
32      }
33 }
34 void del(int &v,int x){
35      if(tree[v].key==x){
36                         if(!tree[v].ch[0]||!tree[v].ch[1]){
37                                                            if(!tree[v].ch[0]) v=tree[v].ch[1];
38                                                            else v=tree[v].ch[0];
39                         }
40                         else{
41                              int f=!(tree[tree[v].ch[0]].pri>tree[tree[v].ch[1]].pri);
42                              rotate(v,f);
43                              tree[v].size--;
44                              del(tree[v].ch[!f],x);
45                         }
46      }
47      else{
48           tree[v].size--;
49           int f=(x<tree[v].key);
50           del(tree[v].ch[!f],x);
51      }
52 }  
53 int find(int v,int x){
54     if(x>tree_size||x<=0) return -1;
55     int mid=1;
56     if(tree[v].ch[0]) mid+=tree[tree[v].ch[0]].size;
57     if(x==mid) return tree[v].key+all;
58     if(x<mid) return find(tree[v].ch[0],x);
59     return find(tree[v].ch[1],x-mid);
60 }
61                 
62 int main()
63 {
64     char opt[2];
65     int k,decans=0;
66     scanf("%d %d",&n,&minn);
67     for(int i=0;i<n;i++){
68             scanf("%s %d",&opt,&k);
69             if(opt[0]==I&&k>=minn){insert(root,k-all);tree_size++;}
70             if(opt[0]==A){all+=k;}
71             if(opt[0]==S){
72                             all-=k;
73                             int tmp;
74                             while((tree_size>0) && ((tmp=find(root,1))<minn)){
75                                                                   tree_size--;
76                                                                   decans++;
77                                                                   del(root,tmp-all);
78                             }
79             }
80             if(opt[0]==F){printf("%d\n",find(root,tree_size+1-k));}
81     }
82     printf("%d\n",decans);
83 
84     return 0;
85 }

 

Noi2004郁闷的出纳员-treap树