郁闷的出纳员 平衡二叉树

Posted CHADLZX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了郁闷的出纳员 平衡二叉树相关的知识,希望对你有一定的参考价值。

这是个经典问题;

用平衡二叉树维护,只不过节点需要多储存一个siz信息,表明在平衡树上的此节点的子节点数;

平衡树稍稍拓展一下的题目,对我而言,写平衡树的代码难度才是关键;

调试了几个小时,这种题目果然需要多练习;

 1 #include<iostream>
 2 #include<cstring>
 3 #include<string>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #include<algorithm>
 7 #include<cmath>
 8 #include<ctime>
 9 using namespace std;
10 const int maxn=101000;
11 const int inf=100000000;
12 char ch;
13 int n,minn=0,delet=0,x,sum=0,root=0,len=0,all=0;
14 struct node{
15     int m,v,siz;
16     int ch[2];
17     int cmp(int x){return m>x?0:1;}
18 }e[maxn<<2];
19 void countsiz(int &x,int d){
20     int k=e[x].ch[d];
21     e[x].siz=e[x].siz-e[k].siz+e[e[k].ch[d^1]].siz;
22     e[k].siz=e[e[k].ch[d]].siz+e[x].siz+1;
23 }
24 void rotate(int &x,int d){
25     countsiz(x,d);
26     int k=e[x].ch[d];
27     e[x].ch[d]=e[k].ch[d^1];
28     e[k].ch[d^1]=x;
29     x=k;
30 }
31 void insert(int &x,int m){
32     if(x==0){x=++len;e[x].m=m;e[x].v=rand();e[x].siz=1;return;}
33     int d=e[x].cmp(m);
34     insert(e[x].ch[d],m);
35     e[x].siz=e[e[x].ch[0]].siz+e[e[x].ch[1]].siz+1;
36     if(e[e[x].ch[d]].v>e[x].v)rotate(x,d);
37 }
38 void found(int m){
39     if(m<minn)return;
40     all++;
41     insert(root,m-delet);
42 }
43 void dfs(int &x){
44     if(x==0)return;
45     if(e[x].m+delet>=minn){dfs(e[x].ch[0]);e[x].siz=e[e[x].ch[0]].siz+e[e[x].ch[1]].siz+1;return;}
46     if(e[x].m+delet<minn){
47         if(e[x].ch[1]){
48             rotate(x,1);
49             dfs(x);
50             if(x==0)return;
51             for(int d=0;d<2;d++)if(e[e[x].ch[d]].v>e[x].v)rotate(x,d);
52             e[x].siz=e[e[x].ch[0]].siz+e[e[x].ch[1]].siz+1;
53         }
54         else{
55             sum+=e[x].siz;
56             x=0;
57         }
58     }
59 }
60 void add(int x){
61     delet+=x;
62     if(x<0)dfs(root);
63 }
64 int dfs(int x,int k,int right){
65     int r=e[x].ch[1];
66     if(x==0)return -inf;
67     if(right+e[r].siz==k)return e[x].m;
68     if(right+e[r].siz>k)return dfs(r,k,right);
69     if(right+e[r].siz<k)return dfs(e[x].ch[0],k,right+e[r].siz+1);
70 }
71 void find(int k){
72     int p=dfs(root,k-1,0);
73     printf("%d\\n",p==-inf?-1:p+delet);
74 }
75 void work(){
76     srand(time(0));
77     scanf("%d%d",&n,&minn);
78     while(n--){
79         scanf(" %c %d",&ch,&x);
80         if(ch==\'I\')found(x);
81         if(ch==\'A\')add(x);
82         if(ch==\'S\')add(-x);
83         if(ch==\'F\')find(x);
84     }
85     cout<<sum<<endl;
86 }
87 int main(){
88     work();
89 }
View Code

 

以上是关于郁闷的出纳员 平衡二叉树的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1503 NOI2004 郁闷的出纳员 平衡树

NOI 2004 郁闷的出纳员 | Treap

bzoj1503 郁闷的出纳员(平衡树,思维)

1503 [NOI2004]郁闷的出纳员

bzoj 1503 郁闷的出纳员

NOI2004 郁闷的出纳员