P3391 【模板】文艺平衡树(Splay)

2023-10-26

题目链接

splay的学习链接


 

基于这道题的关于splay的讲解——将由这篇博客开始。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
inline int read()
{
    int x = 0, t = 1; char ch = getchar();
    while( (ch<'0'||ch>'9' ) && ch!='-') ch=getchar();
    if(ch=='-') { t = -1; ch = getchar(); }
    while( ch<='9' && ch>='0' ) { x=x*10+ch-48; ch=getchar(); }
    return x * t;
}
const int maxN = 1e5 + 7;
int root, tot;
int N, M;
struct node
{
    int ff, val, cnt, size, ch[2], lazy;
    node() { ff = val = cnt = size = ch[0] = ch[1] = lazy = 0; }
    void init(int vv, int fa)
    {
        ff = fa;    val = vv;
        cnt = size = 1;
        lazy = ch[0] = ch[1] = 0;
    }
}t[maxN];
inline void pushup(int rt) { t[rt].size = t[t[rt].ch[0]].size + t[t[rt].ch[1]].size + 1; }
inline void pushdown(int rt)
{
    if(t[rt].lazy)
    {
        t[rt].lazy = 0;
        t[t[rt].ch[0]].lazy ^= 1;
        t[t[rt].ch[1]].lazy ^= 1;
        swap(t[rt].ch[0], t[rt].ch[1]);
    }
}
inline void rotate(int x)  //对x进行旋转操作
{
    int y = t[x].ff, z = t[y].ff;   //x的父亲、x的祖父
    int k = t[y].ch[1] == x;    //x是y的哪个父亲
    t[z].ch[t[z].ch[1] == y] = x;   //z原来的y位置变为x
    t[x].ff = z;    //x的父亲变为z
    t[y].ch[k] = t[x].ch[k^1];  //y的原x在y方向上的子节点变为x的反方向的儿子
    t[t[x].ch[k^1]].ff = y; //更新对应点的父节点
    t[x].ch[k^1] = y;   //y是x的k反方向的节点(恒成立)
    t[y].ff = x;    //更新y的父亲
    pushup(y);  pushup(x);  //x和y的旗下节点的个数会变————必须先更新y再更新x
}
inline void splay(int x, int goal)  //将x旋转为goal的儿子,若goal为0,则将x旋转至根的位置
{
    while(t[x].ff != goal)  //一直旋转到x成为goal的儿子
    {
        int y = t[x].ff, z = t[y].ff;   //父节点、祖父节点
        if(z != goal) (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y);    //若z不是根节点的话,分两种情况讨论
        rotate(x);  //最后都是要旋转x
    }
    if(goal == 0) root = x; //如果goal是0,那个根就是x
}
void find(int x)    //查找值为x的位置并旋转至根节点
{
    int u = root;
    if(!u) return;  //若树为空则直接返回
    while(t[u].ch[x>t[u].val] && x != t[u].val) u = t[u].ch[x>t[u].val];    //若存在儿子并且当前为孩子的值不等于x,跳转至儿子
    splay(u, 0);    //将u旋转至根节点
}
void insert(int x)  //插入x
{
    int u = root, ff = 0;   //当前位置u与父节点ff
    while(u && t[u].val != x)   //当u存在并且还没有移动到当前值
    {
        ff = u; //向下u的儿子
        u = t[u].ch[x>t[u].val];    //大于就向右找,反之向左找
    }
    if(u) t[u].cnt++;   //存在这样的点
    else    //不存在,要新建
    {
        u = ++tot;
        if(ff) t[ff].ch[x>t[ff].val] = u;   //若父节点非根节点、存在父节点的时候
        t[u].init(x, ff);    //建立新节点故左右儿子为空
    }
    splay(u, 0);    //把当前位置移动到根,保证结构平衡
}
int Next(int x, int f)  //0前驱、1后继
{
    find(x);    //找到x的位置并且带到根上去,但是find()找到的点不一定就是恰好等于x的点基本上是"<=x"的点,也有可能是空树
    int u = root;
    if(t[u].val > x && f) return u;     //如果我们找的是后驱并且所找到的根节点就">x"满足后驱的条件就是该点
    if(t[u].val < x && !f) return u;    //如果我们找的是前驱并且满足"<x"
    u = t[u].ch[f];     //在该点的某驱下的方向去取最值
    while(t[u].ch[f^1]) u = t[u].ch[f^1];   //取到尽头
    return u;
}
void Delet(int x)   //删除操作
{
    int last = Next(x, 0), next = Next(x, 1);   //找到前驱和后驱
    splay(last, 0); splay(next, last);      //将前驱放到根节点上去,将后驱链接到前驱上去
    int del = t[next].ch[0];    //那么所对应的要删除的点就是那个既要大于前驱还要小于后驱的点不就是后驱的左儿子
    if(t[del].cnt > 1)
    {
        t[del].cnt--;
        splay(del, 0);
    }
    else t[next].ch[0] = 0;
}
int Kth(int x)
{
    int u = root;
    if(t[u].size < x) return 0;
    while(true)
    {
        pushdown(u);
        int y = t[u].ch[0];
        if(x > t[y].size + t[u].cnt)
        {
            x -= t[y].size + t[u].cnt;
            u = t[u].ch[1];
        }
        else
        {
            if(t[y].size >= x) u = y;
            else return u;
        }
    }
}
inline void work(int l, int r)
{
    l = Kth(l);
    r = Kth(r + 2);
    splay(l, 0);
    splay(r, l);
    t[t[t[root].ch[1]].ch[0]].lazy ^= 1;
}
void write(int u)   //中序遍历——左中右
{
    pushdown(u);
    if(t[u].ch[0]) write(t[u].ch[0]);
    if(t[u].val > 1 && t[u].val <= N + 1) printf("%d ", t[u].val - 1);
    if(t[u].ch[1]) write(t[u].ch[1]);
}
inline void init() { root = tot = 0; }
int main()
{
    scanf("%d%d", &N, &M);
    init();
    for(int i=1; i<=N + 2; i++) insert(i);
    for(int i=1, l, r; i<=M; i++)
    {
//        scanf("%d%d", &l, &r);
        l  = read();    r = read();
        work(l, r);
    }
    write(root);
    printf("\n");
    return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

P3391 【模板】文艺平衡树(Splay) 的相关文章

  • 20210715:力扣第1846题:减小和重新排列组合后的最大元素(java)

    题目 给你一个正整数数组 arr 请你对 arr 执行一些操作 也可以不进行任何操作 使得数组满足以下条件 arr 中 第一个 元素必须为 1 任意相邻两个元素的差的绝对值 小于等于 1 也就是说 对于任意的 1 lt i lt arr l
  • 归并算法

    归并算法 1 在解释算法优缺点的时候 首先要提到2点 一是比较的次数 二是数据要改变或移动的次数 第一个比较好理解 那什么叫改变和移动的次数呢 比如说2这个数据在存储上存储的是10 如果现在2变成4 那么存储就变成了100 这个过程需要将2
  • TestNG测试的并发执行详解

    TestNG在执行测试时 默认suitethreadpoolsize 1 randomizesuites false 即非并发顺序执行测试 但是TestNG提供了多种方式 以支持测试的并发多线程执行 1 针对多个测试规划的情况 为每个tes
  • java实现滑动验证码

    准备工作 1 若干原图片 下文称为原图 2 一张抠图形状图片 下文称为滑块模板 抠出来的图称为滑块 3 一张抠图边框图片 下文称为滑块边框 注意 滑块模板尺寸必须小于原图尺寸 实现思路 1 后端 在若干原图中随机一张原图 2 后端 根据滑块
  • kali linux 连接windows物理主机的安卓模拟器的方法

    不能直连 需要做个端口转发 具体如下 netsh interface portproxy add v4tov4 listenport 18888 listenaddress 0 0 0 0 connectport 62026 connect

随机推荐

  • Mbed在自己的stm32系列平台移植适配(三)

    Mbed在自己的stm32系列平台移植适配 适配平台 cpu STM32F103RCT6 外设 peripheral pin disciption LED1 PC 0 LED2 PC 6 UART5 TX PC 12 no remap UA
  • 贪心算法解决汽车加油问题

    文章目录 1 何为贪心算法 2 贪心算法的特点 3 汽车加油问题 问题描述 图解 代码实现 小结 1 何为贪心算法 贪心算法又称贪婪算法 是指在对问题求解时 总是做出在当前步骤看来是最好的选择 也就是说 不从整体最优上加以考虑 所做出的是在
  • 机器学习和数据挖掘(主流算法介绍)

    对机器学习和数据挖掘的科学定义是这样的 机器学习 Machine Learning ML 是一门多领域交叉学科 涉及概率论 统计学 逼近论 凸分析 算法复杂度理论等多门学科 专门研究计算机怎样模拟或实现人类的学习行为 以获取新的知识或技能
  • html高度塌陷问题的解决方案

    高度塌陷问题 在文档流中 父元素是被子元素给撑开的 也就是说子元素有多高 父元素就有多高 但是当为子元素设置浮动后 元素就会完全脱离文档流导致父元素的高度塌陷 由于父元素高度塌陷了 则父元素的所有元素都会向上移动 这样页面布局就会混乱 所以
  • linux shell脚本替换反斜杠

    1 windows中的脚本 路径均是反斜杠 在linux中 路径是斜杠 需要将反斜杠替换为斜杠 使用sed命令 如下 sed i s g home pp install sql 将 home pp install sql 文件中的 替换为
  • 【C++】C++从入门到精通教程(持续更新...)

    前言 最近在整理之前一些C 资料 重新整理出了一套C 从基础到实践的教程 包含概念 代码 运行结果以及知识点的扩展 感兴趣的后续大家持续关注 以下是更新的文章目录 文章之后整理了一个知识思维导图 看起来比较清楚点 目录 1 C 基础知识 C
  • Java 基础--- 静态绑定与动态绑定

    Java 基础 静态绑定与动态绑定 declared type actual type Static Binding 静态绑定 Dynamic Binding 动态绑定 为什么要区分动态绑定和静态绑定 declared type actua
  • ubuntu 16.04 安装redis 5.0.8

    上一个博客我给Ubuntu 16 04安装了SSH服务器 这篇博客主要展示在该系统上安装最新的redis 5 0 8 redis官方的地址为https redis io download 在Linux安装软件通常有两种方式 第一种是通过各个
  • 9、 Mac 实用软件清单

    Mac 实用软件清单 一 编辑器 Sublime Text 一个比较简洁大方带插件管理系统的流行编辑器 Sublime常用插件 PyCharm 一款 Python 开发集成环境 有专业版和社区版 IntelliJ IDEA 一款 Java
  • STM32独立看门狗IWDG和休眠(低功耗)共存那些事儿

    总结方法 1 寄存器写入标志位方法为主要手段 2 看门狗初始化放在标志位判断后方 3 合理利用单片机复位 标志位复位后不会丢失的特点 4 不同系列单片机寄存器不一样 调试不进入看门狗的做法 调试进入断点时不管停留多久 都不会触发看门狗 论坛
  • Vue实现loading加载动画

    Vue实现loading加载动画 1 在main js里引入axios import axios from http index js 2 在vuex中设置状态 state isLoading false 3 配置拦截器 import ax
  • 宇宙第一 IDE,放弃了 Mac....

    微软发布了 Visual Studio for Mac 退役的公告 公告写道 最新版本 Visual Studio for Mac 17 6 会继续获得额外 12 个月的支持 直至 2024 年 8 月 31 日 并提供针对安全问题的服务更
  • Bootstrap 入门

    一 Bootstrap 简介 框架顾名思义就是一套架构 它会基于自身的特点向用户提供一套较为完整的解决方案 框架的控制权在框架本身 使用者要按照框架所规定的某种规范进行开发 而插件一般是为了解决某个问题专门存在的 其功能单一 并且比较小 前
  • docker windows 下载安装 Update the WSL kernel by running “wsl --update“ or follow instructions at xxx

    下载 Docker Accelerated Containerized Application Development 我这里安装的是windows版的 docker windows 下载安装运行之后提示更新WSL 1 打开cmd窗口记得是
  • firefly如何安装mysql_Firefly安装ROS及ssh远程登录配置

    一 在Linux firefly 3 10 0 上安装ROS indigo 快捷键 CTRL ALT T 打开终端并安装ROS indigo sudo sh c echo deb http packages ros org ros ubun
  • C++ 私有构造函数的作用

    很多情况下要求当前的程序中只有一个object 例如一个程序只有一个和数据库的连接 只有一个鼠标的object 通常我们都将构造函数的声明置于public区段 假如我们将其放入private区段中会发生什么样的后果 这意味着什么 当我们在程
  • (Java)leetcode-84 Largest Rectangle in Histogram( 柱状图中最大的矩形)

    题目描述 难度 hard 给定 n 个非负整数 用来表示柱状图中各个柱子的高度 每个柱子彼此相邻 且宽度为 1 求在该柱状图中 能够勾勒出来的矩形的最大面积 以上是柱状图的示例 其中每个柱子的宽度为 1 给定的高度为 2 1 5 6 2 3
  • SFTP对文件重命名 删除 退出 查看

    常用命令 rename A B ls 空格 t ls 空格 lt sftp gt help Available commands bye Quit sftp
  • php-MD5()函数漏洞

    一 数字与字符串之间的比较 var dump 0 a true var dump 0 a false php把字母开头的字符串转化为整型时 转化为0 前面数字后面字母的话就只取到第一个字母出现的位置之前的数字 二 MD5函数漏洞 GET n
  • P3391 【模板】文艺平衡树(Splay)

    题目链接 splay的学习链接 基于这道题的关于splay的讲解 将由这篇博客开始 include