题意

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

  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. Linux-Qt Quick学习1-Hello world

    Qt作为共平台的开发IDE.实在是强大,在Quick的学习中,与平台无关,我这里使用ubuntu和openSUSE,之所以不用Windows,是因为我想借这个机会过学习一点linux的东西,哪怕是熟悉 ...

  2. linux学习总结----对象

    内置对象: Date new Date() --->系统当前时间 var d=new Date() d.getFullYear() getMonth() getDay() getDate() g ...

  3. ContOS软件包安装【零】

      选择是“Minimal”安装  ,最小化.  越简单,越不容易出错. 1.听一些老鸟分析,选择安装包时应该按最小化原则,即不需要的或者不确定是否需要的就不安装,这样可以最大程度上确保系统安全.(安 ...

  4. windowsserver2008 重新启动计算机命令

    在windowsserver2008中,若要重新启动计算机,可以输入以下命令即可立即重启计算机shutdown -r -t 0命令意义:shutdown在英文中意为关掉,在计算机中即为关机参数意义:- ...

  5. Flask 学习笔记(二):RESTful API

    概括 URL:需要操作的对象,也就是资源 HTTP method:我要对该对象做什么(POST 增.DELETE 删.GET 查.PUT 和 PATCH 改) HTTP status code:操作的 ...

  6. windows下连接hadoop运行eclipse报错Permission denied:

    这是权限问题,试了一下同时也不能在hdfs创建文件夹. 解决: 修改如下hadoop的配置文件:etc/hadoop/hdfs-site.xml,如没有的话可以添加上. <property> ...

  7. 软工实践 - 第二十九次作业 Beta 冲刺(7/7)

    队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10159251.html 作业博客:[班级博客本次作业的链接] (https://edu.cnb ...

  8. CentOS7中rpm,yum软件安装命令

    RPM包常用安装位置说明 /etc/                   配置文件安装目录 /usr/bin/               可执行的命令安装目录 /usr/lib/           ...

  9. javascript中将整数添加千位符号

    如果num是整数的话,将其转换成带千位符号的字符串: Number(num).toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' +  ','); 另 ...

  10. 详细介绍弹性盒模型(display:flex)

    弹性盒模型,即Flexbox,是css3中的新特性,其实弹性盒模型的原身是dispaly:box:这里,我们暂时不考虑旧的,我们只看新的. 为容器指定弹性盒子,只需在父元素(也就是容器)中设置:dis ...