洛谷 P3391 模板文艺平衡树(Splay)
Posted 哈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P3391 模板文艺平衡树(Splay)相关的知识,希望对你有一定的参考价值。
先记一发非旋treap,splay什么的以后再说
基本就是正常的非旋treap维护序列加上一个flip标记,如果某个节点flip为true表示以它为根的子树需要一次翻转。类似线段树lazytag
每次可能要修改某个节点o的任意ch之前,都对o进行一次pushdown。(就是split和merge中)
pushdown的操作是交换o的两个子节点,再将两个子节点的flip标记异或1。
每次进行翻转操作(翻转[l,r]),就把整个序列split成三段[1,l-1],[l,r],[r+1,size]。然后直接将中间一段的根节点的flip标记异或1,再merge回去就行了。
曾经错误:72行两个语句反了;实际上flip不需要修改split和merge,不要多此一举
1 #include<cstdio> 2 #include<algorithm> 3 #include<ctime> 4 using namespace std; 5 template<typename T> 6 class MyVec 7 { 8 private: 9 static const int M_SIZE=200001; 10 int rand1() 11 { 12 static int x=471; 13 return x=(48271LL*x+1)%2147483647; 14 } 15 public: 16 struct Node 17 { 18 Node(){} 19 Node* ch[2]; 20 int r; 21 bool flip; 22 //表示该节点的所有子节点需要flip 23 T v; 24 int size; 25 void upd() 26 { 27 size=1+(ch[0]?ch[0]->size:0)+(ch[1]?ch[1]->size:0); 28 } 29 void pushdown() 30 { 31 if(flip) 32 { 33 Node* t=ch[0];ch[0]=ch[1];ch[1]=t; 34 if(ch[0]) (ch[0]->flip)^=1; 35 if(ch[1]) (ch[1]->flip)^=1; 36 flip=0; 37 } 38 } 39 }nodes[M_SIZE]; 40 private: 41 Node* root; 42 Node* que[M_SIZE]; 43 int que_top; 44 Node* getnode() 45 { 46 return que[que_top--]; 47 } 48 void delnode(Node* x) 49 { 50 que[++que_top]=x; 51 } 52 Node* merge(Node* a,Node* b) 53 { 54 if(a==NULL) return b; 55 if(b==NULL) return a; 56 if(a->r < b->r) 57 { 58 a->pushdown();a->ch[1]=merge(a->ch[1],b);a->upd(); 59 return a; 60 } 61 else 62 { 63 b->pushdown();b->ch[0]=merge(a,b->ch[0]);b->upd(); 64 return b; 65 } 66 } 67 typedef pair<Node*,Node*> P; 68 P split(Node* a,int n) 69 { 70 if(a==NULL) return P(NULL,NULL); 71 P y; 72 a->pushdown();int s=a->ch[0] ? a->ch[0]->size : 0; 73 if(s>=n) 74 { 75 y=split(a->ch[0],n); 76 a->ch[0]=y.second;a->upd(); 77 y.second=a; 78 } 79 else 80 { 81 y=split(a->ch[1],n-s-1); 82 a->ch[1]=y.first;a->upd(); 83 y.first=a; 84 } 85 return y; 86 } 87 Node* kth(Node* o,int k) 88 { 89 if(o==NULL||k<=0||k > o->size) return NULL; 90 P y=split(root,k-1); 91 P y2=split(y.second,1); 92 root=merge(merge(y.first,y2.first),y2.second); 93 return y2.first; 94 } 95 void erase(Node* &o,int k) 96 { 97 if(o==NULL||k<=0||k > o->size) return; 98 P y=split(root,k-1); 99 P y2=split(y.second,1); 100 delnode(y2.first); 101 root=merge(y.first,y2.second); 102 } 103 public: 104 //在第k个之前插入 105 void insert(int k,const T& x) 106 { 107 Node* t=getnode(); 108 t->ch[0]=t->ch[1]=NULL;t->r=rand1();t->v=x;t->flip=0;t->upd(); 109 P y=split(root,k-1); 110 root=merge(merge(y.first,t),y.second); 111 } 112 MyVec() 113 { 114 que_top=M_SIZE-1; 115 for(int i=0;i<M_SIZE;i++) que[i]=nodes+i; 116 root=NULL; 117 } 118 void push_back(const T& x) 119 { 120 insert(size()+1,x); 121 } 122 void pop_back() 123 { 124 erase(root,root->size); 125 } 126 void push_front(const T& x) 127 { 128 insert(1,x); 129 } 130 void pop_front() 131 { 132 erase(root,1); 133 } 134 Node* find_by_order(int k) 135 { 136 return kth(root,k); 137 } 138 T& operator[](int k) 139 { 140 return kth(root,k)->v; 141 } 142 void erase(int k) 143 { 144 erase(root,k); 145 } 146 int size() 147 { 148 return root ? root->size : 0; 149 } 150 //翻转[l,r] 151 void flip(int l,int r) 152 { 153 P y=split(root,l-1); 154 P y2=split(y.second,r-l+1); 155 y2.first->flip^=1; 156 root=merge(merge(y.first,y2.first),y2.second); 157 } 158 }; 159 MyVec<int> x; 160 int n,m,l,r; 161 int main() 162 { 163 int i; 164 scanf("%d%d",&n,&m); 165 for(i=1;i<=n;i++) 166 x.push_back(i); 167 while(m--) 168 { 169 scanf("%d%d",&l,&r); 170 x.flip(l,r); 171 } 172 for(i=1;i<=n;i++) 173 printf("%d ",x[i]); 174 return 0; 175 }
以上是关于洛谷 P3391 模板文艺平衡树(Splay)的主要内容,如果未能解决你的问题,请参考以下文章