洛谷 P6136:【模板】普通平衡树(数据加强版) ← Splay树模板题

【题目来源】
https://www.luogu.com.cn/problem/P6136

【算法分析】
Splay 树简介及代码模板:

https://blog.csdn.net/hnjzsyjyj/article/details/138504578

【代码一: pushdown() 函数版本】
● 本代码为洛谷 P6136 代码。题目来源为:https://www.luogu.com.cn/problem/P6136
● 洛谷 P6136 的代码一可作为 Splay 树的
代码模板,它与洛谷 P3391 代码的差异仅仅在函数 get_val_by_pri() 的定义不同,其他自定义函数 pushup()、pushdown()、rotate()、splay()、insert()、find()、get_pre()、get_suc()、remove()、get_pri_by_val() 完全相同。
● 代码一中 inf 的值按题设定义为 (1<<30)+5,其对应的十进制数为 1073741824。切忌不要定义为传统的 0x3f3f3f3f,因为其对应的十进制数为 7717637477,远超 1073741824。否则,会产生 TLE 和 WA 错误。

#include <bits/stdc++.h>
using namespace std;const int maxn=1.1e6+5;
const int inf=(1<<30)+5;
int n,m;
int root,idx;struct Node {int s[2],v,p; //subtree,val,rootint size,cnt;int lazy;
} tr[maxn];void pushup(int x) {tr[x].size=tr[tr[x].s[0]].size+tr[tr[x].s[1]].size+tr[x].cnt;
}void pushdown(int x) {if(tr[x].lazy) {swap(tr[x].s[0],tr[x].s[1]);tr[tr[x].s[0]].lazy^=1;tr[tr[x].s[1]].lazy^=1;tr[x].lazy=0;}
}void rotate(int x) {int y=tr[x].p;int z=tr[y].p;int k=(tr[y].s[1]==x);tr[z].s[tr[z].s[1]==y]=x, tr[x].p=z;tr[y].s[k]=tr[x].s[k^1], tr[tr[x].s[k^1]].p=y;tr[x].s[k^1]=y, tr[y].p=x;pushup(y), pushup(x);
}void splay(int x,int k) {while(tr[x].p!=k) {int y=tr[x].p;int z=tr[y].p;if(z!=k) {if((tr[y].s[0]==x)^(tr[z].s[0]==y)) rotate(x);else rotate(y);}rotate(x);}if(!k) root=x;
}void insert(int x) {int u=root, p=0;while(u && tr[u].v!=x) {p=u;u=tr[u].s[x>tr[u].v];}if(u) tr[u].cnt++;else {u=++idx;if(p) tr[p].s[x>tr[p].v]=u;tr[u].p=p, tr[u].v=x, tr[u].size=1;tr[u].cnt=1;}splay(u,0);
}void find(int x) {int u=root;while(tr[u].s[x>tr[u].v] && tr[u].v!=x) u=tr[u].s[x>tr[u].v];splay(u,0);
}int get_pre(int x) {find(x);if(tr[root].v<x) return root;int u=tr[root].s[0];while(tr[u].s[1]) u=tr[u].s[1];splay(u,0);return u;
}int get_suc(int x) {find(x);if(tr[root].v>x) return root;int u=tr[root].s[1];while(tr[u].s[0]) u=tr[u].s[0];splay(u,0);return u;
}void remove(int x) {int pre=get_pre(x), suc=get_suc(x);splay(pre,0), splay(suc,pre);int del=tr[suc].s[0];if(tr[del].cnt>1) tr[del].cnt--, splay(del,0);else tr[suc].s[0]=0, splay(suc,0);
}int get_pri_by_val(int x) {insert(x);int ans=tr[tr[root].s[0]].size;remove(x);return ans;
}int get_val_by_pri(int x) { //apply to P6136int u=root;while(true) {if(x<=tr[tr[u].s[0]].size) u=tr[u].s[0];else if(x<=tr[tr[u].s[0]].size+tr[u].cnt) break;else x-=tr[tr[u].s[0]].size+tr[u].cnt, u=tr[u].s[1];}splay(u,0);return tr[u].v;
}/*int get_val_by_pri(int x) { //apply to P3391int u=root;while(true) {pushdown(u);if(x<=tr[tr[u].s[0]].size) u=tr[u].s[0];else if(x==tr[tr[u].s[0]].size+1) return u;else x-=tr[tr[u].s[0]].size+1, u=tr[u].s[1];}return -1;
}*/int main() {insert(-inf);insert(inf);int n,m;cin>>n>>m;for(int i=1; i<=n; i++) {int x;cin>>x;insert(x);}int ans=0, last=0;while(m--) {int op,x;cin>>op>>x;x^=last;if(op==1) insert(x);else if(op==2) remove(x);else if(op==3) ans^=(last=get_pri_by_val(x));else if(op==4) ans^=(last=get_val_by_pri(x+1));else if(op==5) ans^=(last=tr[get_pre(x)].v);else ans^=(last=tr[get_suc(x)].v);}cout<<ans<<endl;return 0;
}/*
in:
6 7
1 1 4 5 1 4
2 1
1 9
4 1
5 8
3 13
6 7
1 4
out:
6
*/


【代码二:不含 pushdown() 函数版本】

#include<bits/stdc++.h>
using namespace std;const int maxn=1.1e6+5;
const int inf=(1<<30)+5;
int n,m;
int root,idx;struct Node {int s[2],v,p; //subtree,val,rootint size,cnt;int lazy;
} tr[maxn];void pushup(int u) {tr[u].size=tr[tr[u].s[0]].size+tr[tr[u].s[1]].size+tr[u].cnt;
}void rotate(int x) {int y=tr[x].p;int z=tr[y].p;int k=(tr[y].s[1]==x);tr[y].s[k]=tr[x].s[k^1],tr[tr[x].s[k^1]].p=y;tr[x].s[k^1]=y,tr[y].p=x;tr[z].s[tr[z].s[1]==y]=x,tr[x].p=z;pushup(y);pushup(x);
}void splay(int x, int k) {while(tr[x].p!=k) {int y=tr[x].p;int z=tr[y].p;if(z!=k) {if((tr[z].s[1]==y) ^ (tr[y].s[1]==x)) rotate(x);else rotate(y);}rotate(x);}if(!k) root=x;
}void insert(int x) {int u=root, p=0;while(u && tr[u].v!=x) {p=u;u=tr[u].s[x>tr[u].v];}if(u) tr[u].cnt++;else {u=++idx;if(p) tr[p].s[x>tr[p].v]=u;tr[u].p=p,tr[u].v=x,tr[u].size=1;tr[u].cnt=1;}splay(u,0);
}void find(int x) {int u=root;while(tr[u].s[x>tr[u].v] && tr[u].v!=x) u=tr[u].s[x>tr[u].v];splay(u,0);
}int get_pre(int x) {find(x);if(tr[root].v<x) return root;int u=tr[root].s[0];while(tr[u].s[1]) u=tr[u].s[1];splay(u,0);return u;
}int get_suc(int x) {find(x);if(tr[root].v>x) return root;int u=tr[root].s[1];while(tr[u].s[0]) u=tr[u].s[0];splay(u,0);return u;
}void remove(int x) {int pre=get_pre(x);int suc=get_suc(x);splay(pre,0);splay(suc,pre);int del=tr[suc].s[0];if(tr[del].cnt>1) tr[del].cnt--, splay(del,0);else tr[suc].s[0]=0, splay(suc,0);
}int get_pri_by_val(int x) {insert(x);int ans=tr[tr[root].s[0]].size;remove(x);return ans;
}int get_val_by_pri(int k) {int u=root;while(true) {if(k<=tr[tr[u].s[0]].size) u=tr[u].s[0];else if(k<=tr[tr[u].s[0]].size+tr[u].cnt) break;else k-=tr[tr[u].s[0]].size+tr[u].cnt, u=tr[u].s[1];}splay(u,0);return tr[u].v;
}int main() {insert(-inf);insert(inf);int n,m;cin>>n>>m;for(int i=1; i<=n; i++) {int x;cin>>x;insert(x);}int ans=0, last=0;while(m--) {int op,x;cin>>op>>x;x^=last;if(op==1) insert(x);else if(op==2) remove(x);else if(op==3) ans^=(last=get_pri_by_val(x));else if(op==4) ans^=(last=get_val_by_pri(x+1));else if(op==5) ans^=(last=tr[get_pre(x)].v);else ans^=(last=tr[get_suc(x)].v);}cout<<ans<<endl;return 0;
}/*
in:
6 7
1 1 4 5 1 4
2 1
1 9
4 1
5 8
3 13
6 7
1 4
out:
6
*/




【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/138504578
https://blog.csdn.net/hnjzsyjyj/article/details/138522947



 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/7672.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyQt6--Python桌面开发(1.安装配置环境)

一.PyQt6简介 PyQt&#xff1a;PyQt是一个功能强大且成熟的GUI框架&#xff0c;基于Qt库。它提供了丰富的组件、布局和主题选项&#xff0c;以及强大的功能和灵活性。PyQt的优点是它具有现代化的外观和丰富的功能&#xff0c;适用于复杂的GUI应用程序。然而&#xff0c;由于Py…

openEuler 22.03 GPT分区表模式下磁盘分区管理

目录 GPT分区表模式下磁盘分区管理parted交互式创建分区步骤 1 执行如下步骤对/dev/sdc磁盘分区 非交互式创建分区步骤 1 输入如下命令直接创建分区。 删除分区步骤 1 执行如下命令删除/dev/sdc1分区。 GPT分区表模式下磁盘分区管理 parted交互式创建分区 步骤 1 执行如下步骤…

明火检测实时识别报警:视觉算法助力安全生产管理

背景与现状 在各种工作、生产环境下&#xff0c;明火的存在往往是潜在的安全隐患。无论是加油站、化工园区、仓储场所还是校园&#xff0c;明火一旦失控就会引发火灾&#xff0c;造成严重的人员伤亡和财产损失。传统的明火检查手段主要依赖于人工巡查和定期的消防检查&#xf…

什么是高级持续威胁(APT)

高级持续性威胁&#xff08;Advanced Persistent Threat&#xff0c;APT&#xff09;&#xff0c;又叫高级长期威胁&#xff0c;是一种复杂的、持续的网络攻击&#xff0c;包含三个要素&#xff1a;高级、长期、威胁。 【高级】是指执行APT攻击需要比传统攻击更高的定制程度和…

预处理器标识#error的目的是什么?

在C和C编程语言中&#xff0c;预处理器标识#error是一个指令&#xff0c;它的目的是在编译过程中生成一个错误信息。当预处理器遇到#error指令时&#xff0c;它会停止编译过程&#xff0c;并显示#error后面的消息作为错误信息。这个指令通常用于确保某些条件在编译时得到满足&a…

人体姿态估计学习

人体姿态估计 1.绪论 人体姿态估计是计算机视觉中一个很基础的问题。从名字的角度来看&#xff0c;可以理解为对“人体”的姿态&#xff08;关键点&#xff0c;比如头&#xff0c;左手&#xff0c;右脚等&#xff09;的位置估计。 一般我们可以这个问题再具体细分成4个任务&…

小米手机短信删除了怎么恢复?这里教你快速解决!

手机已经成为我们生活中不可或缺的一部分&#xff0c;比如小米手机。我们通过手机进行通讯、娱乐、学习等各种活动&#xff0c;其中&#xff0c;短信是我们日常生活中的重要信息来源之一。然而&#xff0c;我们可能会不小心删除了一些重要的短信&#xff0c;这时候我们就会想知…

领航法律科技,法大大多年深耕再获认可!

近日&#xff0c;“乘势破局 第八届新兴法律服务业高峰论坛”在上海隆重举行。作为国内领先的电子签厂商&#xff0c;法大大凭借在法律科技领域的多年深耕与沉淀&#xff0c;荣获“法律科技领航机构”称号。 据悉&#xff0c;新兴法律服务业高峰论坛作为国内首个聚焦“新兴法律…

高等数学笔记(下中)

曲线积分 第一类曲线积分&#xff1a;对弧长的积分计算方法 定理&#xff1a;设 f ( x , y ) f(x,y) f(x,y)在曲线弧 L L L上有定义且连续&#xff0c; L L L的参数方程是 { x φ ( t ) y ψ ( t ) ( α ≤ t ≤ β ) \begin{cases} x\varphi(t)\\ y\psi(t) \end{cases}(\a…

一文了解什么是SSL证书?——值得收藏

SSL证书&#xff0c;全称Secure Sockets Layer证书&#xff0c;是一种网络安全协议的实现方式&#xff0c;现在通常指的是其继任者TLS&#xff08;Transport Layer Security&#xff09;证书&#xff0c;不过习惯上仍称为SSL证书。它的主要作用是确保互联网上的数据传输安全&am…

WebStorm2024版 将项目上传到gitee

目录 一、准备 WebStorm gitee 二、上传代码到Gitee 三、过程中遇到的问题 报错&#xff1a;You may want to first integrate the remote changes (e.g., git pull ...) before pushing again. 报错&#xff1a;fatal: refusing to merge unrelated histories 报错&a…

机器人系统ros2-开发实践05-ROS2 中 tf2的定义及示例说明

1. what ros2 tf2 &#xff1f; tf2的全称是transform2&#xff0c;在ROS&#xff08;Robot Operating System&#xff09;中&#xff0c;它是专门用于处理和变换不同坐标系间位置和方向的库。这个名字来源于“transform”这个词&#xff0c;表示坐标变换&#xff0c;而“2”则…

如何判断代理IP质量?

由于各种原因&#xff08;从匿名性和安全性到绕过地理限制&#xff09;&#xff0c;代理 IP 的使用变得越来越普遍。然而&#xff0c;并非所有代理 IP 都是一样的&#xff0c;区分高质量和低质量的代理 IP 对于确保流畅、安全的浏览体验至关重要。以下是评估代理 IP 质量时需要…

上升实用的Chrome浏览器命令

Chrome浏览器提供了一系列实用的命令行参数&#xff0c;这些参数可以在启动浏览器时使用&#xff0c;或者在Windows系统上通过命令提示符或PowerShell使用。以下是一些常用的Chrome浏览器命令&#xff1a; 1. **-incognito**&#xff1a;打开一个新的隐身窗口。隐身模式下&…

前端递归常见应用

概览 在 JavaScript 中&#xff0c;递归是一种编程技术&#xff0c;指的是函数直接或间接调用自身的过程。 递归通常用于解决可以分解为相同子问题的问题。通过不断地将问题分解成更小的、相似的子问题&#xff0c;直到达到某种基本情况&#xff08;不再需要进一步递归的简单情…

C语言 main( ) 函数的指针数组形参是怎么回事?

一、问题 在使⽤⼀些开发⼯具⽣成C语⾔⽂件时&#xff0c;主函数 mian( ) 中会有参数&#xff0c;这个参数到底是怎么回事⼉呢&#xff1f; 二、解答 mian( ) 称为主函数&#xff0c;是所有程序运⾏的⼊口。 mian( ) 函数是由系统调⽤的&#xff0c;当处于操作命令状态下&…

【算法】滑动窗口——最大连续1的个数

本篇文章讲的是“最大连续1的个数”这道题&#xff0c;从最开始的简单暴力到用滑动窗口算法实现解题的思路历程&#xff0c;有需要借鉴即可。 目录 1.题目2.暴力求解3.滑动窗口解法3.1优化一&#xff1a;end重返start优化&#xff0c;end指针不回退3.2优化二&#xff1a;某一st…

invokeMethod 在 Flutter 中的使用场景与详解

在 Flutter 开发中,我们经常需要与原生平台(Android 或 iOS)进行交互,以实现一些平台特有的功能。invokeMethod 是 Flutter 提供的一个非常重要的 API,它允许我们通过 MethodChannel 与原生平台通信,并调用原生平台定义的方法。本文将详细介绍 invokeMethod 的使用场景、…

深入了解Process Exporter:Prometheus进程监控利器

一、概述 process-exporter主要用来监控进程的运行状态和资源使用情况。 exporter是从/proc目录下获取进程的状态。 二、安装 1、传统安装 下载二进制包&#xff0c;下载链接&#xff1a;https://github.com/ncabatoff/process-exporter/releases/tag/v0.8.1 2、kubernet…

达梦数据库常用命令整理

1.数据库自身信息 1.1 查询实例信息 SQL> select name inst_name from v$instance;行号 INST_NAME ---------- --------- 1 DMSERVER已用时间: 11.211(毫秒). 执行号:15.1.2 查询数据库当前状态 SQL> select status$ from v$instance;行号 STATUS$ -…