Splay

Splay

嗯,之前的博客

重新写了个splay模板,普通平衡树。

  1 #include <cstdio>
  2 
  3 const int N = 100010, INF = 0x7f7f7f7f;
  4 
  5 int val[N], s[N][2], fa[N], cnt[N], S[N], Sp, root, tot, siz[N];
  6 
  7 void out(int p = root) {
  8     if(s[p][0]) {
  9         out(s[p][0]);
 10     }
 11     printf("%d ", val[p]);
 12     if(s[p][1]) {
 13         out(s[p][1]);
 14     }
 15     if(p == root) {
 16         puts("");
 17     }
 18     return;
 19 }
 20 
 21 inline void pushup(int x) {
 22     siz[x] = siz[s[x][0]] + siz[s[x][1]] + cnt[x];
 23     if(!fa[x]) {
 24         root = x;
 25     }
 26     return;
 27 }
 28 
 29 inline void rotate(int x) {
 30     int y = fa[x];
 31     int z = fa[y];
 32     bool f = s[y][1] == x;
 33 
 34     fa[x] = z;
 35     if(z) {
 36         s[z][s[z][1] == y] = x;
 37     }
 38     s[y][f] = s[x][!f];
 39     if(s[x][!f]) {
 40         fa[s[x][!f]] = y;
 41     }
 42     s[x][!f] = y;
 43     fa[y] = x;
 44 
 45     pushup(y);
 46     pushup(x);
 47     return;
 48 }
 49 
 50 inline void splay(int x, int g = 0) {
 51 
 52     /*int y = x;
 53     while(y) {
 54         S[++Sp] = y;
 55         y = fa[y];
 56     }
 57     while(Sp) {
 58         pushdown(S[Sp]);
 59         Sp--;
 60     }*/
 61 
 62     int y = fa[x];
 63     int z = fa[y];
 64     while(y != g) {
 65         if(z != g) {
 66             (s[z][1] == y) ^ (s[y][1] == x) ?
 67             rotate(x) : rotate(y);
 68         }
 69         rotate(x);
 70         y = fa[x];
 71         z = fa[y];
 72     }
 73     return;
 74 }
 75 
 76 inline int np(int x, int f) {
 77     ++tot;
 78     fa[tot] = f;
 79     val[tot] = x;
 80     cnt[tot] = siz[tot] = 1;
 81     return tot;
 82 }
 83 
 84 inline void init() {
 85     root = np(INF, 0);
 86     s[root][0] = np(-INF, root);
 87     pushup(root);
 88     return;
 89 }
 90 
 91 inline void insert(int x) {
 92     int p = root;
 93     while(1) {
 94         // pushdown(p);
 95         siz[p]++;
 96         if(val[p] == x) {
 97             cnt[p]++;
 98             break;
 99         }
100         if(val[p] > x && s[p][0]) {
101             p = s[p][0];
102         }
103         else if(val[p] < x && s[p][1]) {
104             p = s[p][1];
105         }
106         else {
107             bool f = x > val[p];
108             s[p][f] = np(x, p);
109             p = s[p][f];
110             break;
111         }
112     }
113     splay(p);
114     return;
115 }
116 
117 inline int getPbyV(int x) {
118     int p = root;
119     while(1) {
120         if(val[p] > x && s[p][0]) {
121             p = s[p][0];
122         }
123         else if(val[p] < x && s[p][1]) {
124             p = s[p][1];
125         }
126         else {
127             break;
128         }
129     }
130     splay(p);
131     return p;
132 }
133 
134 inline int getlP() {
135     int p = s[root][0];
136     while(s[p][1]) {
137         p = s[p][1];
138     }
139     return p;
140 }
141 
142 inline int getrP() {
143     int p = s[root][1];
144     while(s[p][0]) {
145         p = s[p][0];
146     }
147     return p;
148 }
149 
150 inline void delV(int x) {
151     x = getPbyV(x);
152     if(cnt[x] > 1) {
153         cnt[x]--;
154         pushup(x);
155         return;
156     }
157     int y = getlP();
158     splay(y, x);
159     int z = s[x][1];
160     fa[y] = 0;
161     fa[z] = y;
162     s[y][1] = z;
163     pushup(y);
164     return;
165 }
166 
167 inline int getPreV(int x) {
168     int p = getPbyV(x);
169     if(val[p] < x) {
170         return val[p];
171     }
172     p = getlP();
173     splay(p);
174     return val[p];
175 }
176 
177 inline int getNexV(int x) {
178     int p = getPbyV(x);
179     if(val[p] > x) {
180         return val[p];
181     }
182     p = getrP();
183     splay(p);
184     return val[p];
185 }
186 
187 inline int getRbyV(int x) {
188     int p = getPbyV(x);
189     return siz[s[p][0]];
190 }
191 
192 inline int getVbyR(int k) {
193     k++;
194     int p = root;
195     while(1) {
196         if(siz[s[p][0]] >= k) {
197             p = s[p][0];
198         }
199         else if(siz[s[p][0]] + cnt[p] >= k) {
200             break;
201         }
202         else {
203             k -= siz[s[p][0]] + cnt[p];
204             p = s[p][1];
205         }
206     }
207     splay(p);
208     return val[p];
209 }
210 
211 int main() {
212     init();
213     int n;
214     scanf("%d", &n);
215     for(int i = 1, x, f; i <= n; i++) {
216         scanf("%d%d", &f, &x);
217         if(f == 1) {
218             insert(x);
219         }
220         else if(f == 2) {
221             delV(x);
222         }
223         else if(f == 3) {
224             int t = getRbyV(x);
225             printf("%d\n", t);
226         }
227         else if(f == 4) {
228             int t = getVbyR(x);
229             printf("%d\n", t);
230         }
231         else if(f == 5) {
232             int t = getPreV(x);
233             printf("%d\n", t);
234         }
235         else {
236             int t = getNexV(x);
237             printf("%d\n", t);
238         }
239         //out();
240     }
241 
242     return 0;
243 }
数版splay模板

文艺平衡树,记得从上往下查的时候要pushdown。

  1 #include <cstdio>
  2 #include <algorithm>
  3 
  4 const int N = 100010;
  5 
  6 int val[N], fa[N], s[N][2], S[N], Sp, root, n, siz[N];
  7 bool rev[N];
  8 
  9 inline void pushup(int x) {
 10     siz[x] = siz[s[x][0]] + siz[s[x][1]] + 1;
 11     if(!fa[x]) {
 12         root = x;
 13     }
 14     return;
 15 }
 16 
 17 inline void pushdown(int x) {
 18     if(rev[x]) {
 19         if(s[x][0]) {
 20             rev[s[x][0]] ^= 1;
 21         }
 22         if(s[x][1]) {
 23             rev[s[x][1]] ^= 1;
 24         }
 25         std::swap(s[x][0], s[x][1]);
 26         rev[x] = 0;
 27     }
 28     return;
 29 }
 30 
 31 inline void rotate(int x) {
 32     int y = fa[x];
 33     int z = fa[y];
 34     bool f = (s[y][1] == x);
 35 
 36     fa[x] = z;
 37     if(z) {
 38         s[z][s[z][1] == y] = x;
 39     }
 40     s[y][f] = s[x][!f];
 41     if(s[x][!f]) {
 42         fa[s[x][!f]] = y;
 43     }
 44     s[x][!f] = y;
 45     fa[y] = x;
 46 
 47     pushup(y);
 48     pushup(x);
 49     return;
 50 }
 51 
 52 inline void splay(int x, int g = 0) {
 53     int y = x;
 54     while(y != g) {
 55         S[++Sp] = y;
 56         y = fa[y];
 57     }
 58     while(Sp) {
 59         pushdown(S[Sp]);
 60         Sp--;
 61     }
 62 
 63     y = fa[x];
 64     int z = fa[y];
 65     while(y != g) {
 66         if(z != g) {
 67             (s[z][1] == y) ^ (s[y][1] == x) ?
 68             rotate(x) : rotate(y);
 69         }
 70         rotate(x);
 71         y = fa[x];
 72         z = fa[y];
 73     }
 74     return;
 75 }
 76 
 77 inline int getPbyR(int k) {
 78     int p = root;
 79     while(1) {
 80         pushdown(p);
 81         if(siz[s[p][0]] >= k) {
 82             p = s[p][0];
 83         }
 84         else if(siz[s[p][0]] + 1 == k) {
 85             break;
 86         }
 87         else {
 88             k -= siz[s[p][0]] + 1;
 89             p = s[p][1];
 90         }
 91     }
 92     return p;
 93 }
 94 
 95 inline void reverse(int x, int y) {
 96     y += 2;
 97     x = getPbyR(x);
 98     y = getPbyR(y);
 99     splay(y);
100     splay(x, y);
101     rev[s[x][1]] ^= 1;
102     return;
103 }
104 
105 void out(int x = root) {
106     pushdown(x);
107     if(s[x][0]) {
108         out(s[x][0]);
109     }
110     if(val[x] && val[x] <= n) {
111         printf("%d ", val[x]);
112     }
113     if(s[x][1]) {
114         out(s[x][1]);
115     }
116     return;
117 }
118 
119 int build(int l, int r, int f) {
120     int mid = (l + r) >> 1;
121     int p = mid + 1;
122     val[p] = mid;
123     fa[p] = f;
124     if(l < mid) {
125         s[p][0] = build(l, mid - 1, p);
126     }
127     if(mid < r) {
128         s[p][1] = build(mid + 1, r, p);
129     }
130     pushup(p);
131     return p;
132 }
133 
134 int main() {
135 
136     int m;
137     scanf("%d%d", &n, &m);
138     root = build(0, n + 1, 0);
139     for(int i = 1, x, y; i <= m; i++) {
140         scanf("%d%d", &x, &y);
141         reverse(x, y);
142     }
143     out();
144     return 0;
145 }
序列版splay模板

可以酌情往里面加空间回收,pushdown等。

例题(参考饕餮传奇):

列队(90pts)    郁闷的出纳员   宠物收养场  营业额统计  送花  

永无乡(启发式合并)  [ZJOI2006]书架:直接对节点"编号"进行操作,splay这个编号。

梦幻布丁(启发式合并):开若干个数版splay,维护每个颜色的位置集合。

排序机械臂   维护数列    [AHOI2006]文本编辑器

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 
  5 #define Max 500009
  6 #define Min 500008
  7 
  8 const int N = 500010, INF = 5e8 + 10, EPT = 0x3f3f3f3f;
  9 
 10 int val[N], sum[N], tag[N], fa[N], s[N][2], S[N], Sp, stk[4500010], stp, ans[N], la[N], ra[N], siz[N], root, tot, A[N], n;
 11 bool rev[N];
 12 char str[15];
 13 
 14 inline void exmax(int &a, const int &b) {
 15     if(a < b) {
 16         a = b;
 17     }
 18     return;
 19 }
 20 
 21 inline void pushup(int x) {
 22     int ls = s[x][0], rs = s[x][1];
 23     siz[x] = siz[ls] + siz[rs] + 1;
 24     if(!fa[x]) {
 25         root = x;
 26     }
 27     sum[x] = sum[ls] + sum[rs] + val[x];
 28     ans[x] = val[x];
 29     if(ls && rs) {
 30         exmax(ans[x], ans[ls]);
 31         exmax(ans[x], ans[rs]);
 32         exmax(ans[x], val[x] + la[rs]);
 33         exmax(ans[x], val[x] + ra[ls]);
 34         exmax(ans[x], ra[ls] + val[x] + la[rs]);
 35         la[x] = std::max(la[ls], sum[ls] + val[x]);
 36         exmax(la[x], sum[ls] + val[x] + la[rs]);
 37         ra[x] = std::max(ra[rs], sum[rs] + val[x]);
 38         exmax(ra[x], sum[rs] + val[x] + ra[ls]);
 39     }
 40     else if(ls) {
 41         exmax(ans[x], ans[ls]);
 42         exmax(ans[x], val[x] + ra[ls]);
 43         ra[x] = std::max(val[x], val[x] + ra[ls]);
 44         la[x] = std::max(la[ls], sum[ls] + val[x]);
 45     }
 46     else if(rs) {
 47         exmax(ans[x], ans[rs]);
 48         exmax(ans[x], val[x] + la[rs]);
 49         la[x] = std::max(val[x], val[x] + la[rs]);
 50         ra[x] = std::max(ra[rs], sum[rs] + val[x]);
 51     }
 52     else {
 53         la[x] = ra[x] = val[x];
 54     }
 55     return;
 56 }
 57 
 58 inline void pushdown(int x) {
 59     int ls = s[x][0], rs = s[x][1];
 60     if(rev[x]) {
 61         if(ls) {
 62             rev[ls] ^= 1;
 63             std::swap(la[ls], ra[ls]);
 64         }
 65         if(rs) {
 66             rev[rs] ^= 1;
 67             std::swap(la[rs], ra[rs]);
 68         }
 69         std::swap(s[x][0], s[x][1]);
 70         rev[x] = 0;
 71     }
 72     if(tag[x] != EPT) {
 73         int &c = tag[x];
 74         if(ls) {
 75             val[ls] = tag[ls] = c;
 76             sum[ls] = c * siz[ls];
 77             if(c >= 0) {
 78                 ans[ls] = la[ls] = ra[ls] = sum[ls];
 79             }
 80             else {
 81                 ans[ls] = la[ls] = ra[ls] = c;
 82             }
 83         }
 84         if(rs) {
 85             val[rs] = tag[rs] = c;
 86             sum[rs] = c * siz[rs];
 87             if(c >= 0) {
 88                 ans[rs] = la[rs] = ra[rs] = sum[rs];
 89             }
 90             else {
 91                 ans[rs] = la[rs] = ra[rs] = c;
 92             }
 93         }
 94         c = EPT;
 95     }
 96     return;
 97 }
 98 
 99 void out(int p = root) {
100     pushdown(p);
101     if(s[p][0]) {
102         out(s[p][0]);
103     }
104     printf("%d ", val[p]);
105     if(s[p][1]) {
106         out(s[p][1]);
107     }
108     if(p == root) {
109         puts("");
110     }
111     return;
112 }
113 
114 inline void rotate(int x) {
115     int y = fa[x];
116     int z = fa[y];
117     bool f = (s[y][1] == x);
118 
119     fa[x] = z;
120     if(z) {
121         s[z][s[z][1] == y] = x;
122     }
123     s[y][f] = s[x][!f];
124     if(s[x][!f]) {
125         fa[s[x][!f]] = y;
126     }
127     s[x][!f] = y;
128     fa[y] = x;
129 
130     pushup(y);
131     pushup(x);
132     return;
133 }
134 
135 inline void splay(int x, int g = 0) {
136     int y = x;
137     while(y != g) {
138         S[++Sp] = y;
139         y = fa[y];
140     }
141     while(Sp) {
142         pushdown(S[Sp]);
143         Sp--;
144     }
145 
146     y = fa[x];
147     int z = fa[y];
148     while(y != g) {
149         if(z != g) {
150             (s[z][1] == y) ^ (s[y][1] == x) ?
151             rotate(x) : rotate(y);
152         }
153         rotate(x);
154         y = fa[x];
155         z = fa[y];
156     }
157     return;
158 }
159 
160 inline int getPbyR(int k) {
161     int p = root;
162     while(1) {
163         pushdown(p);
164         if(siz[s[p][0]] >= k) {
165             p = s[p][0];
166         }
167         else if(siz[s[p][0]] + 1 == k) {
168             break;
169         }
170         else {
171             k -= (siz[s[p][0]] + 1);
172             p = s[p][1];
173         }
174     }
175     // splay(p);
176     return p;
177 }
178 
179 inline int split(int l, int r) {
180     l = getPbyR(l);
181     r = getPbyR(r);
182     splay(r);
183     splay(l, r);
184     return l;
185 }
186 
187 inline void change(int l, int r, int c) {
188     int p = split(l, r + 2);
189     int x = s[p][1];
190     tag[x] = val[x] = c;
191     sum[x] = siz[x] * c;
192     if(c >= 0) {
193         ans[x] = la[x] = ra[x] = sum[x];
194     }
195     else {
196         ans[x] = la[x] = ra[x] = c;
197     }
198     pushup(p);
199     pushup(root);
200     return;
201 }
202 
203 inline void reverse(int l, int r) {
204     int p = split(l, r + 2);
205     int x = s[p][1];
206     rev[x] ^= 1;
207     std::swap(la[x], ra[x]);
208     pushup(p);
209     pushup(root);
210     return;
211 }
212 
213 void del(int x) {
214     if(s[x][0]) {
215         del(s[x][0]);
216     }
217     if(s[x][1]) {
218         del(s[x][1]);
219     }
220     stk[++stp] = x;
221     return;
222 }
223 
224 inline void exdel(int l, int r) {
225     int p = split(l, r + 2);
226     int x = s[p][1];
227     del(x);
228     s[p][1] = 0;
229     pushup(p);
230     pushup(root);
231     return;
232 }
233 
234 inline int np(int c, int f) {
235     int x;
236     if(!c) {
237         x = Min;
238     }
239     else if(c > n) {
240         x = Max;
241     }
242     else if(stp) {
243         x = stk[stp--];
244         s[x][0] = s[x][1] = rev[x] = 0;
245         tag[x] = EPT;
246     }
247     else {
248         x = ++tot;
249     }
250     val[x] = A[c];
251     fa[x] = f;
252     return x;
253 }
254 
255 inline int build(int l, int r, int f) {
256     int mid = (l + r) >> 1;
257     int p = np(mid, f);
258     if(l < mid) {
259         s[p][0] = build(l, mid - 1, p);
260     }
261     if(mid < r) {
262         s[p][1] = build(mid + 1, r, p);
263     }
264     pushup(p);
265     return p;
266 }
267 
268 inline void insert(int pos, int len) {
269     int p = split(pos + 1, pos + 2);
270     s[p][1] = build(1, len, p);
271     pushup(p);
272     pushup(root);
273     return;
274 }
275 
276 inline int ask(int l, int r) {
277     int p = split(l, r + 2);
278     int ans = sum[s[p][1]];
279     while(ans < -INF) {
280         ans += INF;
281     }
282     return ans;
283 }
284 
285 int main() {
286     memset(tag, 0x3f, sizeof(tag));
287     int m;
288     scanf("%d%d", &n, &m);
289     for(int i = 1; i <= n; i++) {
290         scanf("%d", &A[i]);
291     }
292     A[0] = A[n + 1] = -INF;
293     root = build(0, n + 1, 0);
294     //out();
295     for(int i = 1, x, y; i <= m; i++) {
296         scanf("%s", str);
297         if(str[0] == 'I') {
298             scanf("%d%d", &x, &y);
299             for(int i = 1; i <= y; i++) {
300                 scanf("%d", &A[i]);
301             }
302             n = y;
303             insert(x, y);
304         }
305         else if(str[0] == 'D') {
306             scanf("%d%d", &x, &y);
307             exdel(x, x + y - 1);
308         }
309         else if(str[0] == 'R') {
310             scanf("%d%d", &x, &y);
311             reverse(x, x + y - 1);
312         }
313         else if(str[0] == 'G') {
314             scanf("%d%d", &x, &y);
315             int t = ask(x, x + y - 1);
316             printf("%d\n", t);
317         }
318         else if(str[2] == 'X') {
319             printf("%d\n", ans[root]);
320         }
321         else {
322             int c;
323             scanf("%d%d%d", &x, &y, &c);
324             change(x, x + y - 1, c);
325         }
326         //out();
327     }
328 
329     return 0;
330 }
维护数列 AC代码

 啊,假装splay过关了......

代码中易错点:

从上往下的操作比如insert,getLP,getPbyR等,要先pushdown。

断开/新建父子关系的时候注意要断完全。有区间赋0操作的时候tag默认设为别的。

 

posted @ 2018-12-17 16:07  huyufeifei  阅读(...)  评论(...编辑  收藏