题意

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

  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. JDBC剖析篇(2):JDBC之PreparedStatement

    一次有人问我为什么要使用JDBC中的PreparedStatement,我说可以“防止SQL注入”,其他的却不能说出个一二三,现在来看看其中的秘密 参考文章: http://www.jb51.net/ ...

  2. [GraphSAGE] docker安装与程序运行

    安装Docker与程序运行 1. requirements.txt Problem: Downloading https://files.pythonhosted.org/packages/69/cb ...

  3. C++STL——vector

    一.相关定义 vector 数组 随机访问迭代器 快速随机访问元素 尾部进行快速随机地插入和删除操作 特征: 能够存放任意类型: 访问vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内 ...

  4. [译]在Python中如何使用额enumerate 和 zip 来迭代两个列表和它们的index?

    enumerate - 迭代一个列表的index和item <Python Cookbook>(Recipe 4.4)描述了如何使用enumerate迭代item和index. 例子如下: ...

  5. wutianqi 博客 母函数

    母函数(Generating function)详解 — Tanky Woo 在数学中,某个序列的母函数(Generating function,又称生成函数)是一种形式幂级数,其每一项的系数可以提供 ...

  6. lintcode-94-二叉树中的最大路径和

    94-二叉树中的最大路径和 给出一棵二叉树,寻找一条路径使其路径和最大,路径可以在任一节点中开始和结束(路径和为两个节点之间所在路径上的节点权值之和) 样例 给出一棵二叉树: 返回 6 标签 动态规划 ...

  7. 《学习OpenCV》课后习题解答8

    题目:(P126) 本章完整讲述了基本的输入/输出编程以及OpenCV的数据结构.下面的练习是基于前面的知识做一些应用,为后面大程序的实现提供帮助. a.创建一个程序实现以下功能:(1)从视频文件中读 ...

  8. Java基础——IO

    一.概述 I/O,Input/Output输入输出.输入机制比如读取文件数据.用户键盘输入等,输出,比如将数据输出到磁盘等. Java的IO是以流(Stream)为基础的. 流的叫法十分形象,你可以想 ...

  9. Activiti工作流(二)——入门Demo及数据库

    上篇博客简单介绍了Activiti流程图的使用,这篇博客我们就根据这个流程图来完成这一个流程.  下图是Activiti的系统服务结构图,在后面的流程中,我们会用到其中的功能组件,如Repositor ...

  10. Centos7安装GUI桌面

    2018-03-02 21:37:48 Centos7-1708成功 yum -y groupinstall "GNOME Desktop"