COGS1829/2457普通/文艺平衡树

超级短的平衡树

核心是可以进行分裂和合并

分裂:

给定一个权值

将原treap分裂成两颗treap

其中一棵所有结点权值都小于等于给定权值,把他叫L树

另一棵所有结点权值都大于给定权值,把他叫R树

合并:

已经有两个treap,其中一个的最大权值严格小于另一颗的最小权值,还是把他们叫LR树

可以按优先级合并成一个treap

 

有了分裂和合并,我们可以做好多事情

 

先看如何分裂:

对于任意一个我正在处理的节点u

如果它的权值v[u]小于给定权值value,那么他的左子树dfs(lson[u])所有点都小于给定权值

所以说这些点都在L树里,把他添加进去,即让L=u

考虑剩下的右子树dfs(rson[u]),由于右子树所有点的权值都大于本节点,并且构成的L树应该满足堆性质

所以如果这些dfs(rson[u])在L树中,那么他们一定在我刚添加进L树中本节点的右子树dfs(rson[L])中

当然他们也可能在R树中

于是这就变成了一个子问题:

将本节点的右子树dfs(rson[u])分裂成L树上本节点的右子树dfs(rson[L])和R树dfs(R)

于是就可以递归调用了

再来看看v[u]大于给定权值的情况

和上面完全对称

于是我们就做完了

树是平衡的,所以整个过程是一个log

 

再看看合并:

考虑正在处理的L和R节点,他们合并后的树的根为root

可以得到加入的节点的优先级必须最小,否则不满足堆性质

由于整个L树的权值都小于R树

假设L的优先级小,那么root=L,这时会发现L的左子树一定是root的左子树,否则不满足bst性质

所以我们又得到了一个子问题:

将L节点的右子树dfs(rson[L])和R树合并成root的右子树dfs(rson[root])

和R优先级小的情况对称

于是就完了

同理,复杂度为一个log

 

然后

添加是把root用value拆成两个树,加点,合并

删除同理,拆分后将子树合并

查找还是同理

第K大按bst查找

于是就完了

普通平衡树:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 100010
  4 #define INF (1<<30)
  5 inline bool isitdigit(char c) {return c<='9'&&c>='0';}
  6 inline int read()
  7 {
  8     register int s,f=1;register char c;
  9     while(!isitdigit(c=getchar())) (c=='-')&&(f=-1);
 10     for(s=c-'0';isitdigit(c=getchar());s=(s<<1)+(s<<3)+c-'0');
 11     return s*f;
 12 }
 13 int n;
 14 struct treap
 15 {
 16     int v[N],w[N],s[N],lson[N],rson[N],c[N],tot,root;
 17    
 18     inline int add(int value)
 19     {
 20         tot++;
 21         c[tot]=1;
 22         v[tot]=value;
 23         w[tot]=rand();s[tot]=1;
 24         return tot;
 25     }
 26     inline void pushup(int o){ s[o]=s[lson[o]]+s[rson[o]]+c[o];}
 27     void spilt(int value,int o,int  &l,int &r)
 28     {
 29         if(!o) {l=r=0;return;}
 30         if(v[o]<=value)
 31         {
 32             l=o;
 33             spilt(value,rson[o],rson[o],r);
 34             pushup(o);return;
 35         }
 36         else
 37         {
 38             r=o;
 39             spilt(value,lson[o],l,lson[o]);
 40             pushup(o);return;
 41         }
 42     }
 43     int merge(int l,int r)
 44     {
 45         if(!l||!r) return l+r;
 46         if(w[l]<=w[r])
 47         {
 48             rson[l]=merge(rson[l],r);
 49             pushup(l);return l;
 50         }
 51         else
 52         {
 53             lson[r]=merge(l,lson[r]);
 54             pushup(r);return r;
 55         }
 56     }
 57     void inserts(int value)
 58     {
 59         int x,y,z,temp;
 60         spilt(value,root,temp,z);
 61         spilt(value-1,temp,x,y);
 62         //printf("temp:%d z:%d x:%d y:%d\n",temp,z,x,y);
 63         if(y) ++c[y],++s[y];
 64         else y=add(value);
 65         root=merge(merge(x,y),z);
 66     }
 67     void deletes(int value)
 68     {
 69         int x,y,z,temp;
 70         y= -1;
 71         spilt(value,root,temp,z);
 72         spilt(value-1,temp,x,y);
 73         if(!y||c[y]==1) root=merge(x,z);
 74         else --c[y],--s[y],root=merge(merge(x,y),z);
 75     }
 76     int search(int value,int & all)
 77     {
 78         int x,y;
 79         spilt(value-1,all,x,y);
 80         int ans=s[x]+1;
 81         all=merge(x,y);
 82         return ans;
 83     }
 84     int find(int k,int  o)
 85     {
 86         if(!o) return 0;
 87         if(k<=s[lson[o]]) return find(k,lson[o]);
 88         if(k>s[lson[o]]+c[o]) return find(k-s[lson[o]]-c[o],rson[o]);
 89         else return v[o];
 90     }
 91     int front (int value)
 92     {
 93         int x,y;
 94         spilt(value-1,root,x,y);
 95         int ans=find(s[x],x);
 96         root=merge(x,y);
 97         return ans;
 98     }
 99     int behind(int value)
100     {
101         int x,y;
102         spilt(value,root,x,y);
103         int ans=find(1,y);
104         root=merge(x,y);
105         return ans;
106     }
107      /*treap()
108     {
109         memset(w,0,sizeof(w));
110         memset(v,0,sizeof(v));
111         memset(c,0,sizeof(c));
112         memset(lson,0,sizeof(lson));
113         memset(rson,0,sizeof(rson));
114         memset(s,0,sizeof(s));
115         tot=root=0;
116         inserts(-INF);
117         inserts(INF);
118         c[tot]=0;
119         c[tot-1]=0;
120         w[tot]=INF;
121         w[tot-1]=INF;
122     }*/
123 }treap;
124 
125 
126 int main()
127 {
128     srand(time(0)); 
129     freopen("phs.in","r",stdin);
130     freopen("phs.out","w",stdout);
131     n=read();
132     for(int i=1;i<=n;i++)
133     {
134         int ope=read(),x=read();
135         switch(ope)
136         {
137             case 1:treap.inserts(x);break;
138             case 2:treap.deletes(x);break;
139             case 3:printf("%d\n",treap.search(x,treap.root));break;
140             case 4:printf("%d\n",treap.find(x,treap.root));break;
141             case 5:printf("%d\n",treap.front(x));break;
142             case 6:printf("%d\n",treap.behind(x));break;
143         }  
144         //printf("%d\n",i);
145     }
146     //treap.v[1000000]=5;
147     //printf("%d",treap.v[1000000]);
148     return 0;
149 }

值得一提的是

拆分操作可以用来处理区间翻转等splay的工作

我们还可以给这个数打上懒标记,当线段树处理

 强啊

文艺平衡树:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 100010
  4 inline bool isitdigit(char c) {return c<='9'&&c>='0';}
  5 inline int read()
  6 {
  7     register int s,f=1;register char c;
  8     while(!isitdigit(c=getchar())) (c=='-')&&(f=-1);
  9     for(s=c-'0';isitdigit(c=getchar());s=(s<<1)+(s<<3)+c-'0');
 10     return s*f;
 11 }
 12 int n,m;
 13 struct treap
 14 {
 15     int v[N],w[N],s[N],lson[N],rson[N],tag[N],c[N],tot,root;
 16     inline void swap(int & a,int & b){int t=a;a=b;b=t;}
 17     inline int add(int value)
 18     {
 19         tot++;c[tot]=s[tot]=1;v[tot]=value;w[tot]=rand();
 20         return tot;
 21     }
 22     inline void pushdown(int o)
 23     {
 24         if(!tag[o]) return;
 25         swap(lson[o],rson[o]);tag[o]^=1;
 26         tag[lson[o]]^=1;tag[rson[o]]^=1;
 27     }    
 28     inline void pushup(int o){ s[o]=s[lson[o]]+s[rson[o]]+c[o];}
 29     void split(int value,int o,int  & l,int & r)
 30     {
 31         if(!o) {l=r=0;return;}
 32         pushdown(o);
 33         if(v[o]<=value) l=o,split(value,rson[o],rson[o],r);
 34         else             r=o,split(value,lson[o],l,lson[o]);
 35         pushup(o);
 36     }
 37     void divide(int k,int o,int & l,int & r)
 38     {
 39         if(!o) {l=r=0;return;}
 40         pushdown(o);
 41         if(k>=s[lson[o]]+c[o]) l=o,divide(k-s[lson[o]]-c[o],rson[o],rson[o],r);
 42         else                  r=o,divide(k,lson[o],l,lson[o]);
 43         pushup(o);
 44     }
 45     int merge(int l,int r)
 46     {
 47         if(!l||!r) return l+r;
 48         pushdown(l);pushdown(r);
 49         if(w[l]<=w[r])
 50         {
 51             rson[l]=merge(rson[l],r);
 52             pushup(l);return l;
 53         }
 54         else
 55         {
 56             lson[r]=merge(l,lson[r]);
 57             pushup(r);return r;
 58         }
 59     }
 60     inline void insert(int value)
 61     {
 62         int x,y,z;
 63         split(value,root,x,z);
 64         split(value-1,x,x,y);
 65         if(y) ++c[y],++s[y];
 66         else y=add(value);
 67         root=merge(merge(x,y),z);
 68     }
 69     void dfs(int o)
 70     {
 71         if(!o) return;
 72         pushdown(o);
 73         dfs(lson[o]);
 74         printf("%d ",v[o]);
 75         dfs(rson[o]);
 76     }
 77     inline void reverse(int l,int r)
 78     {
 79         int x,y,z;
 80         divide(r,root,x,z);
 81         divide(l-1,x,x,y);
 82         tag[y]^=1;
 83         merge(merge(x,y),z);
 84     }
 85 }treap;
 86 int main()
 87 {
 88     srand(time(0)); 
 89     freopen("sph.in","r",stdin);
 90     freopen("sph.out","w",stdout);
 91     n=read(),m=read();
 92     for(register int i=1;i<=n;i++) treap.insert(i);
 93     while(m--)
 94     {
 95         int l=read(),r=read();
 96         treap.reverse(l,r);    
 97     }
 98     treap.dfs(treap.root);
 99     return 0;
100 }

 

posted @ 2018-06-01 16:47  咸鱼炒蒟蒻  阅读(131)  评论(0编辑  收藏  举报