Noi2004郁闷的出纳员-treap树

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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树的主要内容,如果未能解决你的问题,请参考以下文章

1503 [NOI2004]郁闷的出纳员

[BZOJ1503][NOI2004]郁闷的出纳员 无旋Treap

NOI2004 郁闷的出纳员

[BZOJ1503] [NOI2004] 郁闷的出纳员 (treap)

P1486 [NOI2004] 郁闷的出纳员 FHQ-Treap

P1486 [NOI2004] 郁闷的出纳员 FHQ-Treap