[学习笔记]Splay
其实就是一道题占坑啦
[NOI2005]维护数列
分析:
每次操作都要 \(Splay\) 一下
\(Insert\) 操作:重建一棵平衡树,把 \(l\) 变成根,\(l+2\) 变成右子树的根,那棵平衡树就挂在 \(l+2\) 的左子树下
\(Delete\) 操作:直接将其左子树删掉
\(Make-Same\) 操作:把整个区间打一个标记,每次 \(pushdown\) 就好了
\(Reverse\) 操作:类似 \(Make-Same\) 操作
\(Get-Sum\) 操作:直接输出 \(sum\)
\(Max-Sum\) 操作:记 \(Max,lmax,rmax\),每次 \(pushup\) 和 \(pushdown\) 的时候弄一下就好了
\(Code\ Below:\)
#include <bits/stdc++.h>
using namespace std;
const int maxn=6000000+10;
const int inf=0x3f3f3f3f;
int n,m,a[maxn],ch[maxn][2],fa[maxn],key[maxn],siz[maxn],sum[maxn],Max[maxn],lmax[maxn],rmax[maxn],rt,sz;
bool rev[maxn],tag[maxn];
inline int read(){
register int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
}
inline void pushup(int x){
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x];
Max[x]=max(rmax[ch[x][0]]+key[x]+lmax[ch[x][1]],max(Max[ch[x][0]],Max[ch[x][1]]));
lmax[x]=max(lmax[ch[x][0]],sum[ch[x][0]]+key[x]+lmax[ch[x][1]]);
rmax[x]=max(rmax[ch[x][1]],rmax[ch[x][0]]+key[x]+sum[ch[x][1]]);
}
inline void pushdown(int x){
if(tag[x]){
key[ch[x][0]]=key[ch[x][1]]=key[x];
sum[ch[x][0]]=siz[ch[x][0]]*key[x];
sum[ch[x][1]]=siz[ch[x][1]]*key[x];
if(ch[x][0]) Max[ch[x][0]]=max(key[x],sum[ch[x][0]]);
if(ch[x][1]) Max[ch[x][1]]=max(key[x],sum[ch[x][1]]);
lmax[ch[x][0]]=rmax[ch[x][0]]=max(0,sum[ch[x][0]]);
lmax[ch[x][1]]=rmax[ch[x][1]]=max(0,sum[ch[x][1]]);
tag[ch[x][0]]=tag[ch[x][1]]=1;tag[x]=rev[x]=0;
}
if(rev[x]){
swap(lmax[ch[x][0]],rmax[ch[x][0]]);
swap(lmax[ch[x][1]],rmax[ch[x][1]]);
swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]=0;
}
}
inline void rotate(int x){
int y=fa[x],z=fa[y],k=(x==ch[y][1]);
ch[y][k]=ch[x][k^1];fa[ch[x][k^1]]=y;
ch[x][k^1]=y;fa[y]=x;fa[x]=z;
if(z) ch[z][ch[z][1]==y]=x;
pushup(y);pushup(x);
}
inline void splay(int x,int z){
for(int y;(y=fa[x])!=z;rotate(x))
if(fa[y]!=z) rotate((x==ch[y][1])^(y==ch[z][1])?x:y);
if(!z) rt=x;
}
inline int findkth(int x,int k){
while(1){
pushdown(x);
if(k<=siz[ch[x][0]]) x=ch[x][0];
else {
k-=siz[ch[x][0]]+1;
if(!k) return x;
x=ch[x][1];
}
}
}
inline int split(int l,int r){
l=findkth(rt,l);r=findkth(rt,r);
splay(l,0);splay(r,l);
return ch[r][0];
}
inline int query(int l,int r){
return sum[split(l,r)];
}
inline void modify(int l,int r,int v){
int x=split(l,r),y=fa[x],z=fa[y];
key[x]=v;tag[x]=1;sum[x]=siz[x]*key[x];
Max[x]=max(key[x],sum[x]);
lmax[x]=rmax[x]=max(0,sum[x]);
pushup(y);pushup(z);
}
inline void reverse(int l,int r){
int x=split(l,r),y=fa[x],z=fa[y];
if(!tag[x]){
rev[x]^=1;
swap(lmax[x],rmax[x]);
swap(ch[x][0],ch[x][1]);
pushup(y);pushup(z);
}
}
inline void erase(int l,int r){
int x=split(l,r),y=fa[x],z=fa[y];
ch[y][0]=0;pushup(y);pushup(z);
}
int build(int l,int r,int f){
int mid=(l+r)>>1,x=++sz;
if(l==r){
siz[x]=1;sum[x]=Max[x]=a[l];
lmax[x]=rmax[x]=max(0,a[l]);
}
if(l<mid) ch[x][0]=build(l,mid-1,x);
if(mid<r) ch[x][1]=build(mid+1,r,x);
key[x]=a[mid];fa[x]=f;pushup(x);
return x;
}
inline void insert(int l,int r){
for(int i=1;i<=r;i++) a[i]=read();
int z=build(1,r,0),x=findkth(rt,l+1),y=findkth(rt,l+2);
splay(x,0);splay(y,x);
fa[z]=y;ch[y][0]=z;
pushup(y);pushup(x);
}
int main()
{
n=read(),m=read();
Max[0]=a[1]=a[n+2]=-inf;
for(int i=2;i<=n+1;i++) a[i]=read();
rt=build(1,n+2,0);
char op[20];int pos,tot,val;
while(m--){
scanf("%s",op);
if(op[0]=='I'){
pos=read(),tot=read();
insert(pos,tot);
}
if(op[0]=='D'){
pos=read(),tot=read();
erase(pos,pos+tot+1);
}
if(op[0]=='M'){
if(op[2]=='K'){
pos=read(),tot=read(),val=read();
modify(pos,pos+tot+1,val);
}
else printf("%d\n",Max[rt]);
}
if(op[0]=='R'){
pos=read(),tot=read();
reverse(pos,pos+tot+1);
}
if(op[0]=='G'){
pos=read(),tot=read();
printf("%d\n",query(pos,pos+tot+1));
}
}
return 0;
}
[学习笔记]Splay的更多相关文章
- [学习笔记] Splay Tree 从入门到放弃
前几天由于出行计划没有更博QwQ (其实是因为调试死活调不出来了TAT我好菜啊) 伸展树 伸展树(英语:Splay Tree)是一种二叉查找树,它能在O(log n)内完成插入.查找和删除操作.它是由 ...
- 平衡树splay学习笔记#2
讲一下另外的所有操作(指的是普通平衡树中的其他操作) 前一篇的学习笔记连接:[传送门],结尾会带上完整的代码. 操作1,pushup操作 之前学习过线段树,都知道子节点的信息需要更新到父亲节点上. 因 ...
- [学习笔记]平衡树(Splay)——旋转的灵魂舞蹈家
1.简介 首先要知道什么是二叉查找树. 这是一棵二叉树,每个节点最多有一个左儿子,一个右儿子. 它能支持查找功能. 具体来说,每个儿子有一个权值,保证一个节点的左儿子权值小于这个节点,右儿子权值大于这 ...
- 平衡树学习笔记(3)-------Splay
Splay 上一篇:平衡树学习笔记(2)-------Treap Splay是一个实用而且灵活性很强的平衡树 效率上也比较客观,但是一定要一次性写对 debug可能不是那么容易 Splay作为平衡树, ...
- BST,Splay平衡树学习笔记
BST,Splay平衡树学习笔记 1.二叉查找树BST BST是一种二叉树形结构,其特点就在于:每一个非叶子结点的值都大于他的左子树中的任意一个值,并都小于他的右子树中的任意一个值. 2.BST的用处 ...
- 学习笔记 | CDQ分治
目录 前言 啥是CDQ啊(它的基本思想) 例题 后记 参考博文 前言 博主太菜了 学习快一年的OI了 好像没有什么会的算法 更寒碜的是 学一样还不精一样TAT 如有什么错误请各位路过的大佬指出啊感谢! ...
- OI知识点|NOIP考点|省选考点|教程与学习笔记合集
点亮技能树行动-- 本篇blog按照分类将网上写的OI知识点归纳了一下,然后会附上蒟蒻我的学习笔记或者是我认为写的不错的专题博客qwqwqwq(好吧,其实已经咕咕咕了...) 基础算法 贪心 枚举 分 ...
- 平衡树学习笔记(6)-------RBT
RBT 上一篇:平衡树学习笔记(5)-------SBT RBT是...是一棵恐怖的树 有多恐怖? 平衡树中最快的♂ 不到200ms的优势,连权值线段树都无法匹敌 但是,通过大量百度,发现RBT的代码 ...
- 平衡树学习笔记(5)-------SBT
SBT 上一篇:平衡树学习笔记(4)-------替罪羊树 所谓SBT,就是Size Balanced Tree 它的速度很快,完全碾爆Treap,Splay等平衡树,而且代码简洁易懂 尤其是插入节点 ...
随机推荐
- js 正则表达式,匹配邮箱/手机号/用户名
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Django框架之序列化和上传文件
一.Django的序列化(对于ajax请求) Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式. 1)django序列化的使用方法 . ...
- oracle 查看表行数所占空间大小
最新数据库空间有感觉捉急了,上次,删了些数据空了800+G,撑了一个多月,现在还有400+G,每天10G的增量,多少空间也感觉不够用啊. 不能加硬盘,就只有删数据了.. 删数据,人懒,直接找表行最多, ...
- 2018.11.16 bzoj4827: [Hnoi2017]礼物(ntt)
传送门 nttnttntt 入门题. 考虑展开要求的式子∑i=0n−1(xi−yi−c)2\sum_{i=0}^{n-1}(x_i-y_i-c)^2∑i=0n−1(xi−yi−c)2 => ...
- fastjson 错误解决方案详情 com.alibaba.fastjson.JSONException: syntax error, expect {, actual EOF, pos 1410
原因: 前端传递的数组过于复杂,倒是出现这种问题,前端采用vue axios,发送请求,后端java接收代码,实现前后端分离 后端就收fastjson接收json,进行业务处理,后端Controlle ...
- R语言的文件写入
R语言的文件写入 官方文档介绍如下: write.table(x, file = "", append = FALSE, quote = TRUE, sep = " &q ...
- kettle之时间字段默认值为空或’0000-00-00’问题
今天使用kettle从mysql导数到oracle,发现只导了7行后,数据传输就终止了,查看日志信息,报错如下: 报:Couldn't get row from result set问题. 发现从这行 ...
- jquery的bind()和trigger()
本文主要介绍JQuery的trigger()和bind()方法. 1. $(selector).bind(event,data,function)方法为被选元素添加一个或多个事件处理程序,并规定事 ...
- 终端简单使用 &vim编写代码
vim简单实用 & 用vim编写代码 ## 简单介绍 ## vi 1.c 建立1.c(文件存在,则打开1.c) vi共有三种模式: 按esc进入指令模式 按i进入编辑模式(按i光标位置不变 ...
- Leetcode--1. Two Sum(easy)
Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...