码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷 P3391 【模板】文艺平衡树(Splay)

时间:2017-12-01 23:42:45      阅读:396      评论:0      收藏:0      [点我收藏+]

标签:一段   treap   include   node   lazy   异或   div   turn   线段   

先记一发非旋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)

标签:一段   treap   include   node   lazy   异或   div   turn   线段   

原文地址:http://www.cnblogs.com/hehe54321/p/7944692.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!