题意

你应当编写一个数据结构,支持以下操作:

  1. 反转一个区间

题解

我们把在数组中的位置当作权值,这样原序列就在这种权值意义下有序,我们考虑使用splay维护。

对于操作rev[l,r],我们首先把l-1 splay 到根,再把r+1 splay 到根的右子树的根,那么根的右子树的左子树就是区间[l,r]。

显然,这样会用到l-1和r+1。我们考虑添加两个哨兵节点,分别是1和n+2,[1,n]的值再分别加一就好了。

另外,为了防止过多的swap,我们延续线段树中的做法, 打一个lazy标记。与线段树不同的是,由于splay的拓扑结构经常会变化,所以每访问到一个节点,都要下传lazy标记。

注意build的写法。

代码

#include <bits/stdc++.h>
using namespace std;
int n, m, sz, rt;
#ifdef DEBUG
const int maxn = 100;
#else
const int maxn = 100005;
#endif
int fa[maxn], c[maxn][2], id[maxn];
int size[maxn];
bool rev[maxn];
void pushup(int k) {
int l = c[k][0], r = c[k][1];
size[k] = size[l] + size[r] + 1;
}
void pushdown(int k) {
int &l = c[k][0], &r = c[k][1];
if (rev[k]) {
swap(l, r);
rev[l] ^= 1;
rev[r] ^= 1;
rev[k] = 0;
}
}
void zig(int x, int &k) { // do one zig
int y = fa[x], z = fa[y], l, r; // y:father z:grandfather
if (c[y][0] == x) { // zig
l = 0;
} else
l = 1; // zag
r = l ^ 1;
if (y == k)
k = x; // single zig
else { // update grandfather
if (c[z][0] == y)
c[z][0] = x; // zig-zig
else
c[z][1] = x;
}
fa[x] = z;
fa[y] = x;
fa[c[x][r]] = y;
c[y][l] = c[x][r];
c[x][r] = y;
pushup(y);
pushup(x);
}
void splay(int x, int &k) {
while (x != k) {
int y = fa[x], z = fa[y];
if (y != k) {
if (c[y][0] == x ^ c[z][0] == y) // diff:zig-zag or zag-zig
zig(x, k);
else // same:zig-zig or zag-zag
zig(y, k);
}
zig(x, k);
}
}
int find(int k, int rank) {
pushdown(k);
int l = c[k][0], r = c[k][1];
if (size[l] + 1 == rank)
return k;
else if (size[l] >= rank)
return find(l, rank);
else
return find(r, rank - size[l] - 1);
} void rever(int l, int r) {
int x = find(rt, l), y = find(rt, r + 2);
splay(x, rt);
splay(y, c[x][1]);
int z = c[y][0];
rev[z] ^= 1;
}
void build(int l, int r, int f) { // f:last node
if (l > r)
return;
int now = id[l], last = id[f];
if (l == r) {
fa[now] = last;
size[now] = 1;
if (l < f)
c[last][0] = now;
else
c[last][1] = now;
return;
}
int mid = (l + r) >> 1;
now = id[mid];
build(l, mid - 1, mid);
build(mid + 1, r, mid);
fa[now] = last;
pushup(mid);
if (mid < f) {
c[last][0] = now;
} else
c[last][1] = now;
return;
} int main() {
#ifdef DEBUG
freopen("input", "r", stdin);
#endif
scanf("%d %d", &n, &m);
for (int i = 1; i <= n + 2; i++)
id[i] = ++sz;
build(1, n + 2, 0);
rt = (n + 3) >> 1;
for (int i = 1; i <= m; i++) {
int l, r;
scanf("%d %d", &l, &r);
rever(l, r);
}
for (int i = 2; i <= n + 1; i++) {
printf("%d ", find(rt, i) - 1);
}
return 0;
}

[bzoj3223]文艺平衡树——splay的更多相关文章

  1. BZOJ3223 文艺平衡树(splay)

    题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1, ...

  2. JZYZOJ1998 [bzoj3223] 文艺平衡树 splay 平衡树

    http://172.20.6.3/Problem_Show.asp?id=1998 平衡树区间翻转的板子,重新写一遍,给自己码一个板子. #include<iostream> #incl ...

  3. [bzoj3223]文艺平衡树(splay区间反转模板)

    解题关键:splay模板题. #include<cstdio> #include<cstring> #include<algorithm> #include< ...

  4. 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay

    [阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...

  5. luoguP3391[模板]文艺平衡树(Splay) 题解

    链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...

  6. BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Sta ...

  7. bzoj3223 文艺平衡树 (treap or splay分裂+合并)

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 3313  Solved: 1883 [Submit][S ...

  8. Tyvj P1729 文艺平衡树 Splay

    题目: http://tyvj.cn/p/1729 P1729 文艺平衡树 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 此为平衡树系列第二道:文艺平衡树 ...

  9. BZOJ 3223: Tyvj 1729 文艺平衡树(splay)

    速度居然进前十了...第八... splay, 区间翻转,用一个类似线段树的lazy标记表示是否翻转 ------------------------------------------------- ...

随机推荐

  1. vue2.0 watch

    类型:string | Function | Object vue官网解释: 一个对象,键是需要观察的表达式,值是对应回调函数.值也可以是方法名,或者包含选项的对象.Vue 实例将会在实例化时调用 $ ...

  2. Sqlite Datetime类型详解

    日期和时间函数 date(timestring, modifier, modifier, ...) time(timestring, modifier, modifier, ...) datetime ...

  3. Sumsets 递推

    Sumsets Time Limit : 6000/2000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submi ...

  4. selenide UI自动化进阶二 pageObject实现页面管理

    首先定义登录页面,上代码吧 LoginPage.java package com.test.selenium.page; import org.openqa.selenium.By; import s ...

  5. Captcha 验证码Example

    maven依赖 防止和spring中的servlet冲突 <dependency> <groupId>com.github.penggle</groupId> &l ...

  6. CodeForces-1121C System Testing

    题目链接 https://vjudge.net/problem/CodeForces-1121C 题面 Description Vasya likes taking part in Codeforce ...

  7. python之*args和**kwargs参数,以及迭代器

    *args让函数可以接受不限制多个位置参数,**kwargs让函数可以接受不限制多个关键字参数,用法如图 2.迭代器总结

  8. POJ 2166 Heapsort(递推)

    Description A well known algorithm called heapsort is a deterministic sorting algorithm taking O(n l ...

  9. android扁平化ProgressBar--progressWheel

    ProgressWheel是git是一个开源项目,为开发者提供一个扁平化的ProgressBar,并可对其进行深度定制   1,将ProgressWheel的源码拷贝到项目中 public class ...

  10. 【历史】- UNIX发展史(BSD,GNU,linux)

    先前的一個理想 UNIX 系统自 1969 年 Ken Thompson 与 Dennis Ritchie 在美国贝尔电话实验室(Bell Telephone Laboratories)发展出雏形至今 ...