BZOJ3223 文艺平衡树
复习一波splay算法。
先来一道模板题,多开两个哨兵节点便于我们将l-1转到根上,r+1转到l-1的右子树上,这样反转的区间就是根的右子树的左子树。
类似线段树开懒标记,每次操作复杂度O(logN)
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 struct node 5 { 6 int l,r,s,f,lz; 7 }t[N]; 8 int n,m,rt; 9 void merge(int x) 10 { 11 t[x].s=t[t[x].l].s+t[t[x].r].s+1; 12 } 13 void build(int l,int r,int x) 14 { 15 if(l>r)return; 16 int mid=l+r>>1;t[mid].f=x; 17 if(mid<x)t[x].l=mid; 18 else t[x].r=mid; 19 if(l==r) 20 { 21 t[l].f=x; 22 t[l].s=1; 23 return; 24 } 25 build(l,mid-1,mid);build(mid+1,r,mid); 26 merge(mid); 27 } 28 void rotate(int x,int &k) 29 { 30 int y=t[x].f,z=t[y].f; 31 if(y==k)k=x; 32 else{ 33 if(t[z].l==y)t[z].l=x;else t[z].r=x; 34 } 35 if(t[y].l==x)t[t[x].r].f=y,t[y].l=t[x].r,t[x].r=y; 36 else t[t[x].l].f=y,t[y].r=t[x].l,t[x].l=y; 37 t[y].f=x;t[x].f=z; 38 merge(y);merge(x); 39 return; 40 } 41 void splay(int x,int &k) 42 { 43 while(x!=k) 44 { 45 int y=t[x].f;int z=t[y].f; 46 // cout<<x<<" "<<k<<" "<<y<<" "<<z<<endl;system("pause"); 47 if(y!=k){ 48 if(t[y].l==x^t[z].l==y)rotate(x,k); 49 else rotate(y,k); 50 } 51 rotate(x,k); 52 } 53 } 54 void pd(int x) 55 { 56 if(t[x].lz) 57 { 58 swap(t[x].l,t[x].r); 59 t[t[x].l].lz^=1;t[t[x].r].lz^=1;t[x].lz^=1; 60 } 61 } 62 int find(int x,int w) 63 { 64 pd(x); 65 if(t[t[x].l].s+1==w)return x; 66 if(w<=t[t[x].l].s)return find(t[x].l,w); 67 else return find(t[x].r,w-t[t[x].l].s-1); 68 } 69 void write(int x) 70 { 71 if(!x)return; 72 pd(x); 73 write(t[x].l); 74 if(x>1&&x<n+2)printf("%d ",x-1); 75 write(t[x].r); 76 return; 77 } 78 int main() 79 { 80 scanf("%d%d",&n,&m); 81 build(1,n+2,0);int l,r;rt=(n+3)>>1; 82 for(int i=1;i<=m;++i) 83 { 84 scanf("%d%d",&l,&r); 85 int L=find(rt,l);int R=find(rt,r+2); 86 splay(L,rt);splay(R,t[L].r); 87 t[t[R].l].lz^=1; 88 } 89 write(rt); 90 return 0; 91 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。