zoukankan      html  css  js  c++  java
  • luogu 3391

    题解详见洛谷题解区。这里直接放代码了。

    关于实现的几点心得:

    (1)用虚拟节点nil代替空指针NULL/nullptr,对nil的任何操作都不会影响实际节点,从而避免了大量的判断空指针的过程。

    (2)善用throw和<stdexcept>查错。

    (3)下放标记时只需保证从根节点到目标节点依次处理一遍,因此在findKth的过程中不断下放标记,之后splay和旋转过程就不必再检查标记了。、

    (4)打标记要用异或运算(两个标记会相消),不要直接赋值成true。

    (5)初始时将Splay树构造成线形并不会影响均摊复杂度,所以无需用分治法建树。

    代码如下:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <stdexcept>
      5 
      6 int N, K;
      7 
      8 struct Node;
      9 extern Node *nil;
     10 
     11 struct NilFlag {};
     12 struct Node
     13 {
     14     Node *ch[2], *par;
     15     int val, size;
     16     bool flag;
     17 
     18     Node(Node* p, int v): par(p), val(v), size(1), flag(false) {
     19         ch[0] = ch[1] = nil;
     20     }
     21     Node(NilFlag): par(this), val(0), size(0), flag(false) {
     22         ch[0] = ch[1] = this;
     23     }
     24 };
     25 
     26 Node *nil = new Node(NilFlag());
     27 
     28 inline int getDir(Node* p) {
     29     return p == p->par->ch[0] ? 0 : 1;
     30 }
     31 
     32 void pushDown(Node* p)
     33 {
     34     if (!p->flag)
     35         return;
     36 
     37     std::swap(p->ch[0], p->ch[1]);
     38     p->ch[0]->flag ^= 1;
     39     p->ch[1]->flag ^= 1;
     40 
     41     p->flag = false;
     42 }
     43 
     44 void pushUp(Node* p) {
     45     p->size = p->ch[0]->size + p->ch[1]->size + 1;
     46 }
     47 
     48 void rotate(Node* p)
     49 {
     50     Node *temp = p->par;
     51     int dir = getDir(p);
     52 
     53     temp->ch[dir] = p->ch[dir ^ 1];
     54     p->ch[dir ^ 1]->par = temp;
     55 
     56     p->par = temp->par;
     57     temp->par->ch[getDir(temp)] = p;
     58 
     59     temp->par = p;
     60     p->ch[dir ^ 1] = temp;
     61 
     62     pushUp(temp);
     63     pushUp(p);
     64 }
     65 
     66 inline void zig(Node* p) { rotate(p); }
     67 inline void zigzig(Node* p) { rotate(p->par); rotate(p); }
     68 inline void zigzag(Node* p) { rotate(p); rotate(p); }
     69 
     70 struct Splay
     71 {
     72     Node *root;
     73 
     74     Splay(): root(nil) {}
     75     void splay(Node* p, Node* top = nil)
     76     {
     77         while (p->par != top)
     78         {
     79             if (p->par->par == top)
     80             {
     81                 zig(p);
     82                 break;
     83             }
     84             if (getDir(p) == getDir(p->par))
     85                 zigzig(p);
     86             else
     87                 zigzag(p);
     88         }
     89         if (top == nil)
     90             root = p;
     91     }
     92 
     93     void init()
     94     {
     95         root = new Node(nil, 0);
     96         root->size = N + 2;
     97         Node *last = root;
     98 
     99         for (int i = 1; i <= N + 1; i++)
    100         {
    101             Node *cur;
    102             cur = last->ch[1] = new Node(last, i);
    103             cur->size = N + 2 - i;
    104             last = cur;
    105         }
    106     }
    107 
    108     Node* findKth(int k)
    109     {
    110         Node *cur = root;
    111         while (cur != nil)
    112         {
    113             pushDown(cur);
    114 
    115             if (cur->ch[0]->size == k - 1)
    116                 return cur;
    117             if (cur->ch[0]->size < k - 1)
    118             {
    119                 k -= (cur->ch[0]->size + 1);
    120                 cur = cur->ch[1];
    121             }
    122             else
    123                 cur = cur->ch[0];
    124         }
    125         throw std::logic_error("K-th value not found!");
    126     }
    127 
    128     void flipRange(int l, int r)
    129     {
    130         Node *p = findKth(l);
    131         splay(p, nil);
    132 
    133         Node *q = findKth(r + 2);
    134         splay(q, p);
    135 
    136         q->ch[0]->flag ^= 1;
    137     }
    138 
    139     void dfs(Node* p)
    140     {
    141         pushDown(p);
    142 
    143         if (p->ch[0] != nil)
    144             dfs(p->ch[0]);
    145 
    146         if (p->val >= 1 && p->val <= N)
    147             printf("%d ", p->val);
    148 
    149         if (p->ch[1] != nil)
    150             dfs(p->ch[1]);
    151     }
    152     void printAns() { dfs(root); }
    153 };
    154 
    155 int main()
    156 {
    157     scanf("%d%d", &N, &K);
    158     Splay splay;
    159     splay.init();
    160 
    161     for (int l, r, i = 0; i < K; i++)
    162     {
    163         scanf("%d%d", &l, &r);
    164         splay.flipRange(l, r);
    165     }
    166     splay.printAns();
    167 
    168     return 0;
    169 }
  • 相关阅读:
    DevExpress RichEditControl 上下翻页功能 z
    DockManager 如何快速隐藏DockPanel z
    DevExpress SpreadSheet报表模板设置 z
    DocumentManager在标签位置显示气泡框 z
    C#,数据类型扩展 z
    [安卓] 6、列表之ArrayAdapter适配
    [安卓] 5、SeekBar拖动条
    [安卓] 4、CheckBox、RadioButton和Toast简单用法
    [安卓] 3、EditText使用小程序
    [安卓] 2、使用2中方法做按钮监听和图片按钮使用
  • 原文地址:https://www.cnblogs.com/Onlynagesha/p/8780707.html
Copyright © 2011-2022 走看看