一直在想要做这道题,但是被那个硕大的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]维护数列】的更多相关文章

  1. 洛谷 P2042 [NOI2005]维护数列-Splay(插入 删除 修改 翻转 求和 最大的子序列)

    因为要讲座,随便写一下,等讲完有时间好好写一篇splay的博客. 先直接上题目然后贴代码,具体讲解都写代码里了. 参考的博客等的链接都贴代码里了,有空再好好写. P2042 [NOI2005]维护数列 ...

  2. 洛谷P2042 [NOI2005]维护数列

    #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #in ...

  3. 洛谷.2042.[NOI2005]维护数列(Splay)

    题目链接 2017.12.24 第一次写: 时间: 2316ms (1268ms) 空间: 19.42MB (19.5MB)(O2) 注:洛谷测的时间浮动比较大 /* 插入一段数:将这些数先单独建一棵 ...

  4. 【洛谷P2042】维护数列

    题目大意:维护一个序列,支持区间插入,区间删除,区间翻转,查询区间元素和,查询区间最大子段和操作. 题解:毒瘤题...QAQ打完这道题发现自己以前学了一个假的 Splay.. 对于区间操作,用 spl ...

  5. P2042 [NOI2005]维护数列 && Splay区间操作(四)

    到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) ...

  6. P2042 [NOI2005]维护数列[splay或非旋treap·毒瘤题]

    P2042 [NOI2005]维护数列 数列区间和,最大子列和(必须不为空),支持翻转.修改值.插入删除. 练码力的题,很毒瘤.个人因为太菜了,对splay极其生疏,犯了大量错误,在此记录,望以后一定 ...

  7. Luogu P2042 [NOI2005]维护数列(平衡树)

    P2042 [NOI2005]维护数列 题意 题目描述 请写一个程序,要求维护一个数列,支持以下\(6\)种操作:(请注意,格式栏中的下划线'_'表示实际输入文件中的空格) 输入输出格式 输入格式: ...

  8. BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)

    手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.net/suncongbo/article/details/82027387 题目链接: (l ...

  9. Luogu P2042 [NOI2005]维护数列

    题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线' _ '表示实际输入文件中的空格) 输入输出格式 输入格式: 输入文件的第 1 行包含两个数 N 和 M, ...

  10. P2042 [NOI2005]维护数列

    思路 超级恶心的pushdown 昏天黑地的调 让我想起了我那前几个月的线段树2 错误 这恶心的一道题终于过了 太多错误,简直说不过来 pushup pushdown 主要就是这俩不太清晰,乱push ...

随机推荐

  1. iOS-----------关于UDID

    最近看友盟的SDK更新日志:(设备系统的正常升级不会改变OpenUDID) Apple公司于2013年5月1日开始,拒绝采集UDID的App上架App Store. 为适应Apple公司的这一政策,2 ...

  2. iOS----------关于Cornerstone的偏好设置

    应用场景:有时候我们的项目会导入一些第三方.a文件,但是当我们在svn上check out下来的时候,会发现少了一些.a文件.于是乎项目就报错了. 针对这种情况,我们应该怎么办呢? 1.先打开Corn ...

  3. asp.net core参数保护之自定义要保护的参数类型

    asp.net core参数保护之自定义要保护的参数类型 Intro 为了实现 asp.net core 下的参数保护,扩展了asp.net core 中 DataProtection,可以自动化的保 ...

  4. python爬虫实战:利用scrapy,短短50行代码下载整站短视频

    近日,有朋友向我求助一件小事儿,他在一个短视频app上看到一个好玩儿的段子,想下载下来,可死活找不到下载的方法.这忙我得帮,少不得就抓包分析了一下这个app,找到了视频的下载链接,帮他解决了这个小问题 ...

  5. mssql sqlserver 索引专题

    摘要: 下文将详细讲述sql server 索引的相关知识,如下所示: 实验环境: sql server 2008 R2 sqlserver索引简介: mssql sqlsever 索引分类简介 ms ...

  6. kylin简单优化cube

    优化Cube 层次结构 理论上,对于N维,你最终会得到2 ^ N维组合.但是对于某些维度组,不需要创建这么多组合.例如,如果您有三个维度:洲,国家,城市(在层次结构中,“更大”维度首先出现).在深入分 ...

  7. awk、grep、sed是linux操作文本的三大利器,也是必须掌握的linux命令之一

    awk.grep.sed是linux操作文本的三大利器,也是必须掌握的linux命令之一.三者的功能都是处理文本,但侧重点各不相同,其中属awk功能最强大,但也最复杂.grep更适合单纯的查找或匹配文 ...

  8. Ubuntu系统分配存储空间的建议以及给Ubuntu系统根目录扩容方法(从20GB追加100GB)

    当初准备装双系统时,也思考了很久分配多少空间给Ubuntu16.04系统,查了许多资料,大多意思是‘/’目录总共给20GB,其他的给/home.网上资料推荐的大多跟这篇文章一样:https://blo ...

  9. ElasticSearch(七):Java操作elasticsearch基于smartcn中文分词查询

    package com.gxy.ESChap01; import java.net.InetAddress; import org.elasticsearch.action.search.Search ...

  10. Django-CRM项目学习(二)-模仿admin实现stark

    开始今日份整理 1.stark模块基本操作 1.1 stark模块的启动 保证django自动的加载每一个app下的stark.py文件 创建django项目,创建stark项目,start app ...