NOI2005 维护数列(splay)
学了半天平衡树,选择了一道题来写一写,发现题目是裸的splay模板,但是还是写不好,这个的精髓之处在于在数列的某一个位置加入一个数列,类似于treap里面的merge,然后还学到了题解里面的的回收空间做法,利用时间换取空间也是一种非常不错的做法,由于题目中有区间翻转的操作,所以只能用splay来写,然后对于一些区间最大值和区间最大子序列的询问我们可以用类似于线段树的合并操作来维护,总的来说这是一道对于树形数据结构非常好的运用的题目。——by VANE

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e6+;
int n,m,rt,cnt;
int a[N],id[N],fa[N],c[N][];
int sum[N],sz[N],v[N],mx[N],lx[N],rx[N];
bool tag[N],rev[N];
queue<int> q;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>'') {if(ch=='-') f=-f; ch=getchar();}
while(ch>=''&&ch<='') {x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void pushup(int x)
{
int l=c[x][],r=c[x][];
sum[x]=sum[l]+sum[r]+v[x];
sz[x]=sz[l]+sz[r]+;
mx[x]=max(mx[l],max(mx[r],rx[l]+v[x]+lx[r]));
lx[x]=max(lx[l],sum[l]+v[x]+lx[r]);
rx[x]=max(rx[r],sum[r]+v[x]+rx[l]);
}
inline void pushdown(int x)
{
int l=c[x][],r=c[x][];
if(tag[x])
{
rev[x]=tag[x]=;
if(l) tag[l]=,v[l]=v[x],sum[l]=v[x]*sz[l];
if(r) tag[r]=,v[r]=v[x],sum[r]=v[x]*sz[r];
if(v[x]>=)
{
if(l) lx[l]=rx[l]=mx[l]=sum[l];
if(r) lx[r]=rx[r]=mx[r]=sum[r];
}
else
{
if(l) lx[l]=rx[l]=,mx[l]=v[x];
if(r) lx[r]=rx[r]=,mx[r]=v[x];
}
}
if(rev[x])
{
rev[x]=;rev[l]^=;rev[r]^=;
swap(lx[l],rx[l]);swap(lx[r],rx[r]);
swap(c[l][],c[l][]);swap(c[r][],c[r][]);
}
}
inline void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l=(c[y][]==x),r=l^;
if(y==k) k=x;else c[z][c[z][]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(x);
}
inline void splay(int x,int &k)
{
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if(c[z][]==y ^ c[y][]==x) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
inline int find(int x,int rk)
{
pushdown(x);
int l=c[x][],r=c[x][];
if(sz[l]+==rk) return x;
if(sz[l]>=rk) return find(l,rk);
return find(r,rk-sz[l]-);
}
inline void recycle(int x)
{
int &l=c[x][],&r=c[x][];
if(l) recycle(l);
if(r) recycle(r);
q.push(x);
fa[x]=l=r=tag[x]=rev[x]=;
}
inline int split(int k,int tot)
{
int x=find(rt,k),y=find(rt,k+tot+);
splay(x,rt);splay(y,c[x][]);
return c[y][];
}
inline void query(int k,int tot)
{
int x=split(k,tot);
printf("%d\n",sum[x]);
}
inline void modify(int k,int tot,int val)
{
int x=split(k,tot),y=fa[x];
v[x]=val;tag[x]=;sum[x]=sz[x]*val;
if(val>=) lx[x]=rx[x]=mx[x]=sum[x];
else lx[x]=rx[x]=,mx[x]=val;
pushup(y);pushup(fa[y]);
}
inline void rever (int k,int tot)
{
int x=split(k,tot),y=fa[x];
if(!tag[x])
{
rev[x]^=;
swap(c[x][],c[x][]);
swap(lx[x],rx[x]);
pushup(y);pushup(fa[y]);
}
}
inline void erase(int k,int tot)
{
int x=split(k,tot),y=fa[x];
recycle(x);c[y][]=;
pushup(y);pushup(fa[y]);
}
inline void build(int l,int r,int f)
{
int mid=l+r>>,now=id[mid],pre=id[f];
if(l==r)
{
mx[now]=sum[now]=a[l];
lx[now]=rx[now]=max(a[l],);
sz[now]=;
}
if(l<mid) build(l,mid-,mid);
if(mid<r) build(mid+,r,mid);
v[now]=a[mid];fa[now]=pre;
pushup(now);
c[pre][mid>=f]=now;
}
inline void insert(int k,int tot)
{
for(int i=;i<=tot;++i) a[i]=read();
for(int i=;i<=tot;++i)
{
if(!q.empty()) id[i]=q.front(),q.pop();
else id[i]=++cnt;
}
build(,tot,);
int z=id[+tot>>];
int x=find(rt,k+),y=find(rt,k+);
splay(x,rt);splay(y,c[x][]);
fa[z]=y;c[y][]=z;
pushup(y);pushup(x);
}
int main()
{
n=read();m=read();
mx[]=a[]=a[n+]=-inf;
for(int i=;i<=n;++i) a[i+]=read();
for(int i=;i<=n+;++i) id[i]=i;
build(,n+,);
rt=n+>>;cnt=n+;
int k,tot,val;char ch[];
while(m--)
{
scanf("%s",ch);
if(ch[]!='M'||ch[]!='X') k=read(),tot=read();
if(ch[]=='I') insert(k,tot);
if(ch[]=='D') erase(k,tot);
if(ch[]=='M')
{
if(ch[]=='X') printf("%d\n",mx[rt]);
else val=read(),modify(k,tot,val);
}
if(ch[]=='R') rever(k,tot);
if(ch[]=='G') query(k,tot);
}
}
NOI2005 维护数列(splay)的更多相关文章
- P2042 [NOI2005]维护数列 && Splay区间操作(四)
到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) ...
- 洛谷 P2042 [NOI2005]维护数列-Splay(插入 删除 修改 翻转 求和 最大的子序列)
因为要讲座,随便写一下,等讲完有时间好好写一篇splay的博客. 先直接上题目然后贴代码,具体讲解都写代码里了. 参考的博客等的链接都贴代码里了,有空再好好写. P2042 [NOI2005]维护数列 ...
- P2042 [NOI2005]维护数列[splay或非旋treap·毒瘤题]
P2042 [NOI2005]维护数列 数列区间和,最大子列和(必须不为空),支持翻转.修改值.插入删除. 练码力的题,很毒瘤.个人因为太菜了,对splay极其生疏,犯了大量错误,在此记录,望以后一定 ...
- 洛谷.2042.[NOI2005]维护数列(Splay)
题目链接 2017.12.24 第一次写: 时间: 2316ms (1268ms) 空间: 19.42MB (19.5MB)(O2) 注:洛谷测的时间浮动比较大 /* 插入一段数:将这些数先单独建一棵 ...
- BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)
手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.net/suncongbo/article/details/82027387 题目链接: (l ...
- 数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列
339. [NOI2005] 维护数列 时间限制:3 s 内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际 ...
- [NOI2005]维护数列(区间splay)
[NOI2005]维护数列(luogu) 打这玩意儿真是要了我的老命 Description 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文 ...
- [NOI2005] 维护数列
[NOI2005] 维护数列 题目 传送门 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1 ...
- Luogu P2042 [NOI2005]维护数列(平衡树)
P2042 [NOI2005]维护数列 题意 题目描述 请写一个程序,要求维护一个数列,支持以下\(6\)种操作:(请注意,格式栏中的下划线'_'表示实际输入文件中的空格) 输入输出格式 输入格式: ...
随机推荐
- 说一说ASP.NET web.config 加密及解密方法 (代码)
/// <summary> /// 保护web.config的加密和解密 /// </summary> public class ProtectHelper { /// < ...
- 关于HttpWebRequest发生服务器协议冲突的解决办法
WinForm下的app.config文件中添加: <system.net> <settings> <httpWebRequest useUnsafeHe ...
- 天梯赛 L2-001 紧急救援 (最短路 dij)
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当其他城市有紧急求 ...
- Django之ModelForm(一)
要说ModelForm,那就先说Form吧! 先给出一个Form示例: models.py from django.db import models class UserType(models.Mod ...
- 【译】第五篇 SQL Server代理理解代理错误日志
本篇文章是SQL Server代理系列的第五篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.在第四篇中我们看到 ...
- python 第二章 对象与类型
可变对象和不可变对象 1,可变对象,list(列表),dict(字典),集合(set),字节数组. 2,不可变对象,数值类型,字符串,字节串,元组(具体形式 ()). 注意条件:可变和不可变指的是该对 ...
- tp修改的写法
- linux常用函数简单介绍
mmap函数简介: mmap函数是unix/linux下的系统调用,来看<Unix Netword programming>卷二12.2节对mmap的介绍: The mmap functi ...
- tomcat+java的web程序持续占cpu高问题调试【转】
转自 tomcat+java的web程序持续占cpu问题调试 - 像风一样的自由 - CSDN博客http://blog.csdn.net/five3/article/details/28416771 ...
- Python多态、鸭子类型
一.多态 多态指的是一类事物有多种形态. 动物有多种形态:人,狗,猪 import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.ab ...