zoukankan      html  css  js  c++  java
  • 洛谷 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 }
  • 相关阅读:
    递归打印99乘法表
    递归对一个数组求和
    在控制台打印出99乘法表
    ie9以下浏览器不兼容placeholder的解决方案
    二列布局 左边固定宽度 右边响应
    Scala并发编程实战初体验及其在Spark源码中的应用解析之Scala学习笔记-56
    Scala中隐式转换内幕操作规则揭秘、最佳实践及其在Spark中的应用源码解析之Scala学习笔记-55
    Scala中隐式对象代码实战详解之Scala学习笔记-54
    Scala中隐式类代码实战详解之Scala学习笔记-53
    Scala中上下文界定内幕中的隐式参数与隐式参数的实战详解及其在Spark中的应用源码解析之Scala学习笔记-52
  • 原文地址:https://www.cnblogs.com/hehe54321/p/7944692.html
Copyright © 2011-2022 走看看