洛谷 P2042 【[NOI2005]维护数列】
一直在想要做这道题,但是被那个硕大的Splay标签压垮了
好了,切入正题
这道题应该是我第二次用splay来维护区间问题 我还是太菜了QAQ
其实思路也很简单,就是以每一个位置的下标来进行维护,然后其实就是跟权值树是一模一样的了
然后再具体说一下
为了保证效率,像线段树和文艺平衡树一样,我们可以维护一个\({lazytag}\),然后在需要向下查询时再向下查询就行
然后我们考虑两种标记各自下传的先后顺序
我们可以发现,如果一个区间内已经被“同化”,即进行了\(make-same\)操作,这个时候,翻转也没有了意义。
关于求最大子段和,这个部分就跟原来用线段树解决此类问题是一模一样的,维护一个gss标记,然后对其做DP就行了。
然后这一道题和其他平衡树的题最大的一点不同是它是区间插入,区间删除。为了提升效率,我们可以考虑先将每一次要加入的一段区间预处理成一棵平衡树,然后再直接插入,这样的话效率会有很大的提升
然后,这道题差不多就完了
具体就看代码吧
#pragma G++ optimize(3)
#pragma GCC optimize(3)
#pragma G++ optimize(2)
#pragma GCC optimize(2)
#pragma G++ optimize("-Ofast")
#pragma GCC optimize("-Ofast")
#include<queue>
#include<cstdio>
#include<cstring>
#define dir(p) (son[fa[p]][1]==p)
#define inf 0x3f3f3f
using namespace std;
const int maxn=6e5+10;
char opt[30];
int n,m,ncnt,root;
queue<int>q;
int siz[maxn],son[maxn][2],sum[maxn],val[maxn];
int gss[maxn],lx[maxn],rx[maxn],fa[maxn];
int sam[maxn],rev[maxn],a[maxn],id[maxn];
void swap(int &a,int &b)
{
a^=b^=a^=b;
}
int max(int a,int b)
{
return a>b?a:b;
}
inline int read()
{
register int num=0,f=1;
register char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
num=num*10+ch-'0';
ch=getchar();
}
return num*f;
}
void upd(register int t)
{
int l=son[t][0],r=son[t][1];
siz[t]=siz[l]+siz[r]+1;
sum[t]=sum[l]+sum[r]+val[t];
lx[t]=max(lx[l],sum[l]+val[t]+lx[r]);
rx[t]=max(rx[r],sum[r]+val[t]+rx[l]);
gss[t]=max(rx[l]+lx[r]+val[t],max(gss[l],gss[r]));
}
void pushdown(register int t)
{
int l=son[t][0],r=son[t][1];
if(sam[t])
{
sam[t]=rev[t]=0;
if(l)
{
sam[l]=1,val[l]=val[t];
sum[l]=val[l]*siz[l];
lx[l]=rx[l]=max(sum[l],0);
gss[l]=val[l]<0?val[l]:sum[l];
}
if(r)
{
sam[r]=1,val[r]=val[t];
sum[r]=val[r]*siz[r];
lx[r]=rx[r]=max(sum[r],0);
gss[r]=val[r]<0?val[r]:sum[r];
}
}
if(rev[t])
{
rev[t]=0,rev[l]^=1,rev[r]^=1;
swap(lx[l],rx[l]),swap(rx[r],lx[r]);
swap(son[l][0],son[l][1]);
swap(son[r][0],son[r][1]);
}
}
inline int node(register int x)
{
int cur;
if(q.empty()) cur=++ncnt;
else cur=q.front(),q.pop();
son[cur][0]=son[cur][1]=fa[cur]=0;
val[cur]=sum[cur]=gss[cur]=x;
lx[cur]=rx[cur]=max(0,x);
sam[cur]=rev[cur]=0;
siz[cur]=1;
return cur;
}
inline int kth(register int x)
{
int t=root;
while(1)
{
pushdown(t);
if(son[t][0]&&x<=siz[son[t][0]])
t=son[t][0];
else if(x>siz[son[t][0]]+1)
{
x-=siz[son[t][0]]+1;
t=son[t][1];
}
else
return t;
}
}
void rotate(register int p)
{
int fp=fa[p],ffp=fa[fp],way=dir(p);
son[fp][way]=son[p][way^1];
fa[son[p][way^1]]=fp;
son[ffp][dir(fp)]=p;
fa[p]=ffp;
son[p][way^1]=fp;
fa[fp]=p;
upd(fp),upd(p);
}
void splay(register int p,register int g)
{
while(fa[p]!=g)
{
int fp=fa[p],ffp=fa[fp];
if(ffp!=g)
{
if(dir(fp)==dir(p)) rotate(fp);
else rotate(p);
}
rotate(p);
}
if(!g) root=p;
}
inline void insert(register int x,register int y)
{
int u=kth(x+1),v=kth(x+2);
splay(u,0),splay(v,u);
son[v][0]=y,fa[y]=v;
upd(v),upd(u);
}
inline void recycle(register int x)
{
if(son[x][0]) recycle(son[x][0]);
if(son[x][1]) recycle(son[x][1]);
q.push(x);
}
inline void remove(register int x,register int y)
{
int u=kth(x),v=kth(x+y+1);
splay(u,0),splay(v,u);
recycle(son[v][0]);
son[v][0]=0;
upd(v),upd(u);
}
inline int qsum(register int x,register int y)
{
int u=kth(x),v=kth(x+y+1);
splay(u,0),splay(v,u);
return sum[son[v][0]];
}
int build(register int l,register int r,int *qaq)
{
if(l>r) return 0;
int mid=(l+r)>>1,cur=node(qaq[mid]);
if(l==r) return cur;
if((son[cur][0]=build(l,mid-1,qaq))) fa[son[cur][0]]=cur;
if((son[cur][1]=build(mid+1,r,qaq)))fa[son[cur][1]]=cur;
upd(cur);
return cur;
}
inline void update(register int x,register int y,register int z)
{
int u=kth(x),v=kth(x+y+1);
splay(u,0),splay(v,u);
int w=son[v][0];
sam[w]=1,val[w]=z,sum[w]=siz[w]*z;
lx[w]=rx[w]=max(sum[w],0);
if(z<0) gss[w]=z;
else gss[w]=sum[w];
upd(v),upd(u);
}
inline void reverse(register int x,register int y)
{
int u=kth(x),v=kth(x+y+1);
splay(u,0),splay(v,u);
int w=son[v][0];
if(!sam[w])
{
rev[w]^=1;
swap(son[w][0],son[w][1]);
swap(lx[w],rx[w]);
upd(v),upd(u);
}
}
int main()
{
n=read();
m=read();
for(register int i=2;i<=n+1;++i)
a[i]=read();
gss[0]=val[0]=-inf;
a[1]=a[n+2]=-inf;
n+=2;
build(1,n,a);
root=1;
int pos,num,tot;
for(register int i=1;i<=m;++i)
{
scanf("%s",opt);
if(opt[0]=='I')
{
pos=read(),num=read();
memset(a,0,sizeof a);
for(register int j=1;j<=num;++j)
a[j]=read();
insert(pos,build(1,num,a));
}
else if(opt[0]=='D')
{
pos=read(),num=read();
remove(pos,num);
}
else if(opt[0]=='M'&&opt[3]=='E')
{
pos=read(),num=read(),tot=read();
update(pos,num,tot);
}
else if(opt[0]=='R')
{
pos=read(),num=read();
reverse(pos,num);
}
else if(opt[0]=='G')
{
pos=read(),num=read();
printf("%d\n",qsum(pos,num));
}
else if(opt[0]=='M'&&opt[1]=='A'&&opt[2]=='X')
printf("%d\n",gss[root]);
}
return 0;
}
洛谷 P2042 【[NOI2005]维护数列】的更多相关文章
- 洛谷 P2042 [NOI2005]维护数列-Splay(插入 删除 修改 翻转 求和 最大的子序列)
因为要讲座,随便写一下,等讲完有时间好好写一篇splay的博客. 先直接上题目然后贴代码,具体讲解都写代码里了. 参考的博客等的链接都贴代码里了,有空再好好写. P2042 [NOI2005]维护数列 ...
- 洛谷P2042 [NOI2005]维护数列
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #in ...
- 洛谷.2042.[NOI2005]维护数列(Splay)
题目链接 2017.12.24 第一次写: 时间: 2316ms (1268ms) 空间: 19.42MB (19.5MB)(O2) 注:洛谷测的时间浮动比较大 /* 插入一段数:将这些数先单独建一棵 ...
- 【洛谷P2042】维护数列
题目大意:维护一个序列,支持区间插入,区间删除,区间翻转,查询区间元素和,查询区间最大子段和操作. 题解:毒瘤题...QAQ打完这道题发现自己以前学了一个假的 Splay.. 对于区间操作,用 spl ...
- P2042 [NOI2005]维护数列 && Splay区间操作(四)
到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) ...
- P2042 [NOI2005]维护数列[splay或非旋treap·毒瘤题]
P2042 [NOI2005]维护数列 数列区间和,最大子列和(必须不为空),支持翻转.修改值.插入删除. 练码力的题,很毒瘤.个人因为太菜了,对splay极其生疏,犯了大量错误,在此记录,望以后一定 ...
- Luogu P2042 [NOI2005]维护数列(平衡树)
P2042 [NOI2005]维护数列 题意 题目描述 请写一个程序,要求维护一个数列,支持以下\(6\)种操作:(请注意,格式栏中的下划线'_'表示实际输入文件中的空格) 输入输出格式 输入格式: ...
- BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)
手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.net/suncongbo/article/details/82027387 题目链接: (l ...
- Luogu P2042 [NOI2005]维护数列
题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线' _ '表示实际输入文件中的空格) 输入输出格式 输入格式: 输入文件的第 1 行包含两个数 N 和 M, ...
- P2042 [NOI2005]维护数列
思路 超级恶心的pushdown 昏天黑地的调 让我想起了我那前几个月的线段树2 错误 这恶心的一道题终于过了 太多错误,简直说不过来 pushup pushdown 主要就是这俩不太清晰,乱push ...
随机推荐
- Visual Studio无法调试
一.最近Visual studio调试不起来,运行完报错 二.解决方法 打开 调试>>>>选项>>>>常规>>>对ASP.NET启用 ...
- 【Linux】【Apatch Tomcat】Linux、CentOS7安装最新版Apartch Tomcat环境
1.前言 相当嫌弃,博客园搞掉了我快写完的 Tomcat. 请先安装 :[Linux][Java]CentOS7安装最新版Java1.8.191运行开发环境 虽然安装Tomcat没啥技术,但是还是记录 ...
- MySQL 处理海量数据时的一些优化查询速度方法
查询速度慢的原因 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O 吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6 ...
- 宇宙第一开发工具:vs2019 开发Python
1.初步认识 现在人工智能逐步进入人们的视野,人工智能开发也越来越火. 而python语言,被作为大数据库开发的首选语言之一~.前一段时间vs2019预览版发布.相信不少小伙伴已经开始使用,vs201 ...
- webmagic 爬取网页所有文章的标题时间作者和内容
package com.ij34; import us.codecraft.webmagic.Site; import us.codecraft.webmagic.Page; import us.co ...
- Oracle 12c用户和安全管理
前言: Oracle 12c的多租户(multitenant)环境与SQL Server的架构非常相似,CDB$ROOT类似于master.PDB$SEED类似于model.各个pluggable d ...
- VSCode的Python扩展下程序运行的几种方式与环境变量管理
在VSCode中编写Python程序时,由于有些地方要使用环境变量,但是发现设置的环境变量有时不起作用,花了点时间研究了一下,过程不表,直接说结论. 首先,环境变量的设置,Python扩展中有三种方式 ...
- 《常见排序算法--PHP实现》
原文地址: 本文地址:http://www.cnblogs.com/aiweixiao/p/8202360.html Original 2018-01-02 关注 微信公众号 程序员的文娱情怀 1.概 ...
- C#基础知识之面向对象以及面向对象的三大特性
在C#基础知识之类和结构体中我详细记录了类.类成员.重载.重写.继承等知识总结.这里就记录一下对面向对象和面向对象三大特性的广义理解. 一.理解面向对象 类是面向对象编程的基本单元,面向对象思想其实就 ...
- yum源 Python3 Django mysql安装
yum 源安装 yum源位置: yum源仓库的地址 在/etc/yum.repos.d/,并且只能读出第一层的repo文件 yum仓库的文件都是以.repo结尾的 linux软件包管理 yum工具如同 ...