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 }