luogu 3391 - 文艺平衡树 - Splay,区间翻转

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

关于实现的几点心得:

(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 }

 

posted @ 2018-04-10 17:19  Onlynagesha  阅读(281)  评论(0编辑  收藏  举报