题目描述

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1

分析

不懂splay可以看一下我的博客:【传送门】
这道题目就是用splay来实现区间反转的,这个东西听说好像是LCT用splay的原因,我也不清楚没有学过LCT。
很明显,我们这道题目维护的不是权值,而是区间的编号(虽然好像还是权值),那么翻转操作就是交换两个子树的儿子的关系,但是如果每一次都暴力翻转\(O(mlog^2n)\),就做一个懒标记。
如果一个区间被旋转了两次,那么很明显,这个区间又变回去了,那么我们就维护一个标记表示表示以下的区间是否被翻转过。
那么剩下来的答案其实就是二叉查找树的中序遍历(BST的性质)。

ac代码

#include <bits/stdc++.h>
#define ll long long
#define ms(a, b) memset(a, b, sizeof(a))
#define inf 0x3f3f3f3f
#define N 100005
using namespace std;
template <typename T>
inline void read(T &x) {
    x = 0; T fl = 1;
    char ch = 0;
    while (ch < '0' || ch > '9') {
        if (ch == '-') fl = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    x *= fl;
}
struct Splay {
    int rt, tot;
    struct node {
        int ch[2], fa, val, sz, fg;
        void init(int nod, int ft) {
            fa = ft;
            ch[0] = ch[1] = 0;
            sz = 1;
            val = nod;
        }
    }tr[N << 1];
    Splay() {
        ms(tr, 0);
        rt = tot = 0;
    }
    void pushup(int nod) {
        tr[nod].sz = tr[tr[nod].ch[0]].sz + tr[tr[nod].ch[1]].sz + 1;
    }
    void pushdown(int nod) {
        if (!tr[nod].fg) return;
        tr[tr[nod].ch[0]].fg ^= 1;
        tr[tr[nod].ch[1]].fg ^= 1;
        tr[nod].fg = 0;
        swap(tr[nod].ch[0], tr[nod].ch[1]);
    }
    void rotate(int nod) {
        int fa = tr[nod].fa, gf = tr[fa].fa, k = tr[fa].ch[1] == nod;
        tr[gf].ch[tr[gf].ch[1] == fa] = nod;
        tr[nod].fa = gf;
        tr[fa].ch[k] = tr[nod].ch[k ^ 1];
        tr[tr[nod].ch[k ^ 1]].fa = fa;
        tr[nod].ch[k ^ 1] = fa;
        tr[fa].fa = nod;
        pushup(fa);
        pushup(nod);
    }
    void splay(int nod, int goal) {
        while (tr[nod].fa != goal) {
            int fa = tr[nod].fa, gf = tr[fa].fa;
            if (gf != goal) {
                if ((tr[gf].ch[0] == fa) ^ (tr[fa].ch[0] == nod)) rotate(nod);
                else rotate(fa);
            }
            rotate(nod);
        }
        if (goal == 0) rt = nod;
    }
    int kth(int k) {
        int u = rt;
        while (1) {
            pushdown(u);
            int lc = tr[u].ch[0];
            if (tr[lc].sz >= k) u = lc;
            else if (tr[lc].sz + 1 == k) return u;
            else k -= tr[lc].sz + 1, u = tr[u].ch[1];
        }
    }
    void insert(int x) {
        int u = rt, ft = 0;
        while (u) {
            ft = u;
            u = tr[u].ch[x > tr[u].val];
        }
        u = ++ tot;
        if (ft) tr[ft].ch[x > tr[ft].val] = u;
        tr[u].init(x, ft);
        splay(u, 0);
    }
    void solve(int l, int r) {
        l = kth(l);
        r = kth(r + 2);
        splay(l, 0);
        splay(r, l);
        tr[tr[tr[rt].ch[1]].ch[0]].fg ^= 1;
    }
}splay;
int n, m;
void dfs(int nod) {
    splay.pushdown(nod);
    if (splay.tr[nod].ch[0]) dfs(splay.tr[nod].ch[0]);
    if (splay.tr[nod].val >= 2 && splay.tr[nod].val <= n + 1) printf("%d ", splay.tr[nod].val - 1);
    if (splay.tr[nod].ch[1]) dfs(splay.tr[nod].ch[1]);
}
int main() {
    read(n); read(m);
    for (int i = 1; i <= n + 2; i ++) splay.insert(i);
    while (m --) {
        int l, r;
        read(l); read(r);
        splay.solve(l, r);
    }
    dfs(splay.rt);
    return 0;
}

[luogu3391][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. [bzoj3223]文艺平衡树——splay

    题意 你应当编写一个数据结构,支持以下操作: 反转一个区间 题解 我们把在数组中的位置当作权值,这样原序列就在这种权值意义下有序,我们考虑使用splay维护. 对于操作rev[l,r],我们首先把l- ...

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

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

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

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

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

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

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

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

  9. Tyvj P1729 文艺平衡树 Splay

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

随机推荐

  1. C++常用宏

    宏是由 #define 定义而来,在预处理阶段进行宏展开,它的格式是: #define N 2 + 2 // 仅仅是字符串替换 #define N (2 + 2) // 也是字符串 ,但是是(2 + ...

  2. 在layui中使用ajax不起作用

    又是一个坑,坑了我一个下午.在layui插件中使用jquery的ajax请求,一点反应都没有,不管是改成get还是post请求,后台毫无反应,前端谷歌调试也没有报半点错. js代码如下: layui. ...

  3. 当mysql报错1045时的解决方法

    2.用记事本打开 添加 打开后,搜索mysqld关键字 找到后,在mysqld下面添加skip-grant-tables,保存退出. 如果保存在了c盘里不能修改那么就采用这样的方法 然后就可以修改c盘 ...

  4. RBAC模型

    1.RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成“用户-角 ...

  5. 记一次生产mysql数据误操作恢复过程

    提示:建议每次对数据库进行修改时都做下备份 注意:以下Mysql开启的是row格式的binlog日志,确定到误操作具体时间可能有些麻烦,默认的格式就能很快找出来.这里开启row的原因是还有一种更快的方 ...

  6. shiro使用ajax登陆实现,success但页面无法跳转的问题

    首先:简述一下登陆的后台流程 页面提交——>对应controller中的方法——>对应Realm认证——>controller返回 json 这样,无论成功与否,都有返回值,可以用 ...

  7. Android SDK Tools 24.3.2 Build脚本Bug

    如下图版本: 在%Android_home%\tools\ant\build.xml中, 在483行附近, 少了aidl,aapt,dx, zipalign四个变量的声明. 加上就OK了. <p ...

  8. query中对应的OnSetText和onGetText事件

    今天在看代码的时候遇到一个问题,query中的某个字段和在表中显示的不是一个值,我觉得很奇怪,于是找了很久,才知道为什么,原来是query中的OnSetText和onGetText事件在作怪,经过一番 ...

  9. has invalid type <class 'numpy.ndarray'>, must be a string or Tensor

    转自: https://blog.csdn.net/jacke121/article/details/78833922 has invalid type <class 'numpy.ndarra ...

  10. 梯度下降取负梯度的简单证明,挺有意思的mark一下

    本文转载自:http://blog.csdn.net/itplus/article/details/9337515