【xsy1629】可持久化序列 - 可持久化平衡树
题意
你现在要用数据结构维护一个长度为n的序列。
这个序列支持三种操作:
1 l r:将序列中的第l项到第r项这一段翻转。
2 l r:查询序列中[l,r]这一段的和。
3 p:回到第p个历史版本。
每一个翻转操作的时候记作序列处于一次新的版本,初始的版本是0。
每一个回到历史版本之后再操作的版本都是一个最新版本,不是第p+1版本。
\(1\leq n\leq 50000\)
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
const int N=65536;
const int M=65536;
const int S=8388608;
int n,m;
int a[N];
namespace Treap {
int rt[M],nowVer,allVer;
int tot;
struct Node {
int c[2]; int rev;
int fix; //fix=dep
int dat,sum;
int siz;
Node(int _fix=0,int _dat=0,int _siz=0) {
c[0]=c[1]=rev=0;
fix=_fix;
dat=sum=_dat;
siz=_siz;
}
}tr[S];
struct D {
int c[2];
D(void) {
c[0]=c[1]=0;
}
};
void Update(int x) {
tr[x].sum=tr[tr[x].c[0]].sum+tr[tr[x].c[1]].sum+tr[x].dat;
tr[x].siz=tr[tr[x].c[0]].siz+tr[tr[x].c[1]].siz+1;
}
int New_Node(int key,int fix,int dat) {
int x=++tot;
tr[x]=Node(fix,dat,1);
return x;
}
int Copy_Node(int form) {
int x=++tot;
tr[x]=tr[form];
return x;
}
int Build(int *a,int l,int r,int dep) {
int mid=(l+r)>>1;
int x=New_Node(mid,dep,a[mid]);
if (l<mid)
tr[x].c[0]=Build(a,l,mid-1,dep+1);
if (mid<r)
tr[x].c[1]=Build(a,mid+1,r,dep+1);
Update(x);
return x;
}
void Clear(int x) {
if (!tr[x].rev) return; tr[x].rev=0;
if (tr[x].c[0]>0) {
tr[x].c[0]=Copy_Node(tr[x].c[0]);
tr[tr[x].c[0]].rev^=1;
}
if (tr[x].c[1]>0) {
tr[x].c[1]=Copy_Node(tr[x].c[1]);
tr[tr[x].c[1]].rev^=1;
}
swap(tr[x].c[0],tr[x].c[1]);
}
D Split(int x,int rk) {
D t; if (!x) return t;
int x1=Copy_Node(x); Clear(x1);
if (rk<=tr[tr[x1].c[0]].siz) {
t=Split(tr[x1].c[0],rk);
tr[x1].c[0]=t.c[1]; Update(x1);
t.c[1]=x1;
}
else if (rk==tr[tr[x1].c[0]].siz+1) {
t.c[1]=tr[x1].c[1];
tr[x1].c[1]=0; Update(x1);
t.c[0]=x1;
}
else {
t=Split(tr[x1].c[1],rk-1-tr[tr[x1].c[0]].siz);
tr[x1].c[1]=t.c[0]; Update(x1);
t.c[0]=x1;
}
return t;
}
int Merge(int x1,int x2) {
if (!x1) return x2;
if (!x2) return x1;
if (tr[x1].fix<tr[x2].fix) {
int x3=Copy_Node(x1);
Clear(x3);
tr[x3].c[1]=Merge(tr[x3].c[1],x2);
Update(x3);
return x3;
}
else {
int x3=Copy_Node(x2);
Clear(x3);
tr[x3].c[0]=Merge(x1,tr[x3].c[0]);
Update(x3);
return x3;
}
}
}
int rd(void) {
int x=0,f=1; char c=getchar();
while (!isdigit(c)) {
if (c=='-') f=-1;
c=getchar();
}
while (isdigit(c)) {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
void Goto(int p) {
using namespace Treap;
nowVer=p;
}
void Reverse(int l,int r) {
using namespace Treap;
D t1=Split(rt[nowVer],r);
D t2=Split(t1.c[0],l-1); //use t2.c[1]
int x=Copy_Node(t2.c[1]);
tr[x].rev^=1;
rt[++allVer]=Merge(Merge(t2.c[0],x),t1.c[1]);
nowVer=allVer;
}
int Query(int l,int r) {
using namespace Treap;
D t1=Split(rt[nowVer],r);
D t2=Split(t1.c[0],l-1);
return tr[t2.c[1]].sum;
}
int main(void) {
#ifndef ONLINE_JUDGE
freopen("N.in","r",stdin);
freopen("N.out","w",stdout);
#endif
n=rd(),m=rd();
rep(i,1,n) a[i]=rd();
Treap::rt[0]=Treap::Build(a,1,n,1);
rep(i,1,m) {
int c=rd();
switch (c) {
case 1: {
int l=rd(),r=rd();
Reverse(l,r);
break;
}
case 2: {
int l=rd(),r=rd();
int ans=Query(l,r);
printf("%d\n",ans);
break;
}
case 3: {
int p=rd();
Goto(p);
break;
}
}
}
return 0;
}
【xsy1629】可持久化序列 - 可持久化平衡树的更多相关文章
- 可持久化Trie & 可持久化平衡树 专题练习
[xsy1629]可持久化序列 - 可持久化平衡树 http://www.cnblogs.com/Sdchr/p/6258827.html [bzoj4260]REBXOR - Trie 事实上只是一 ...
- luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)
luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include< ...
- Redis的两种持久化方式-快照持久化和AOF持久化
Redis为了内部数据的安全考虑,会把本身的数据以文件形式保存到硬盘中一份,在服务器重启之后会自动把硬盘的数据恢复到内存(redis)的里边,数据保存到硬盘的过程就称为"持久化"效 ...
- Redis的两种持久化方式-快照持久化(RDB)和AOF持久化
Redis为了内部数据的安全考虑,会把本身的数据以文件形式保存到硬盘中一份,在服务器重启之后会自动把硬盘的数据恢复到内存(redis)的里边,数据保存到硬盘的过程就称为“持久化”效果. redis有两 ...
- Hibernate,Session方法使得java对象进入持久化状态;持久化对象特征
以下情况java对象进入持久化状态: session.save()方法把临时对象转变为持久化对象. session.load()和session.get()方法得到的对象总是处于持久化状态. sess ...
- Redis数据持久化之AOF持久化
一.RDB持久化的缺点创建RDB文件需要将服务器所有的数据库的数据都保存起来,这是一个非常耗费资源和时间的操作,所以服务器需要隔一段时间才能创建一个新的RDB文件,就也是说创建RDB文件的操作不能执行 ...
- JMS学习(五)--ActiveMQ中的消息的持久化和非持久化 以及 持久订阅者 和 非持久订阅者之间的区别与联系
一,消息的持久化和非持久化 ①DeliveryMode 这是传输模式.ActiveMQ支持两种传输模式:持久传输和非持久传输(persistent and non-persistent deliver ...
- redis系列:RDB持久化与AOF持久化
前言 什么是持久化? 持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘).持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中.XML数 ...
- RabbitMQ学习笔记(6)----RabbitMQ 持久化和非持久化
持久化:将交换机或队列数据保存到磁盘,服务器宕机或重启之后依然存在. 非持久化:将交换机或队列的数据保存到内存中,服务器宕机或重启之后数据将不存在. 在RabbitMQ中也提供了持久化和非持久化方式. ...
随机推荐
- 相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了!
相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了! 先说图片X×dpi=点数dotX是图片实际尺寸,简单点,我们只算图片的高吧,比如说拍了张图片14 ...
- PARENT VIEW INVALIDATE
如果启动display list,parentview 调用invalidate,子view是不会是去调用onDraw的,因为直接调用displaylist了,如果parentview认为子view应 ...
- express框架路由配置及congtroller自动加载
express框架在node官方推荐的一个框架,关于如何入门的文章,已经很多了,我就不在累赘了,本文的核心是如何修改文件使得更接近一个MVC的框架 express原生是通过require的方式实现了模 ...
- Java数据结构之字符串模式匹配算法---KMP算法2
直接接上篇上代码: //KMP算法 public class KMP { // 获取next数组的方法,根据给定的字符串求 public static int[] getNext(String sub ...
- php就业网版本已改版成功
php就业网简介:www.php91.net,专注于Thinkphp框架教程的php框架学习中心.同时也有小崔老师自学php的教程,与你一起成长哦 同时,php就业网教程部分:http://www.p ...
- T-sql 查询
------------------case---when-------的使用--------------------- select userAccount , eatingDate , c ...
- sql 保留两位小数+四舍五入
1. ROUND(该函数,只是负责四舍五入到两位小数,但是不负责截断 只留两位小数,例如下例:) 关于ROUND函数,我们平常理解为4舍5入,如: print ROUND(13.145, 2); 结果 ...
- JavaScript使用技巧(1)——JS常用的函数
1.字符串对象函数和属性 函数: charAt():返回在指定位置的字符. charCodeAt():返回在指定的位置的字符的 Unicode 编码. concat():连接字符串. indexOf( ...
- C/C++ 堆和栈的区别
堆和栈的区别 一个由C/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其 操作方式类似于数据结构中的栈. 2.堆区(h ...
- Win10 Hyper-V 配置
Win10 Hyper-V 配置 安装 Hyper 程序和功能 -> 启用和关闭windows -> Hyper-V Hyper-V 虚拟网类型 外部网络 [外网/物理机/虚拟机] 内部网 ...