news 2026/4/2 18:23:31

进阶数据结构Splay应用-维护数列

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
进阶数据结构Splay应用-维护数列

引言

该问题几乎包含了所有的s p l a y splaysplay操作, 如果不了解s p l a y splaysplay可以单击这里

题目-维护数列

问题分析

因为涉及到区间翻转操作, 线段树无法实现(线段树解决的是区间属性问题)

其实最复杂的操作是求区间的最大
子段和
, 可以考虑s p l a y splaysplay维护的节点信息

s p l a y splaysplay每个节点表示一个数字, 多个点构成的的中序遍历就是希望求的序列, 因此中序遍历维护的是序列

算法步骤

s p l a y splaysplay维护的节点信息

实现细节

如果一个点有延迟标记, 这个点的权值存储的是执行延迟标记之前的值还是执行延迟标记之后的值需要自己去定义

因为执行s a m e samesame或者r e v revrev延迟标记, 会对当前节点的值(m a x v , l m , r m , s u m maxv, lm, rm, summaxv,lm,rm,sum)产生影响, 可以定义当前节点的值(m a x v , l m , r m , s u m maxv, lm, rm, summaxv,lm,rm,sum)是延迟标记操作之后的值

具体的来说

对于当前节点, 如果打上了延迟标记, 那么将该节点的m a x v , l m , r m , s u m maxv, lm, rm, summaxv,lm,rm,sum都计算一遍


并且在节点执行push down延迟操作的时候, 不仅仅是直接将子节点打上标记, 而且将子节点的m a x v , l m , r m , s u m maxv, lm, rm, summaxv,lm,rm,sum计算一遍

在删除过程中需要进行内存回收优化内存, 也就是将删除的节点回收到节点池

因此初始化的时候,ms = sum = v, 不能是max(v, 0)

代码实现

注意事项:

#include<bits/stdc++.h>usingnamespacestd;constintN=5e5+10,INF=1e9;intn,m;structNode{ints[2],p,v;intrev,same,cnt;intms,ls,rs,sum;// 因为内存回收机制的存在, 必须在此刻重置rev和same的延迟标记voidinit(int_v,int_p){s[0]=s[1]=0;p=_p,v=_v;cnt=1;rev=same=0;sum=ms=v;ls=rs=max(v,0);}}tr[N];// nodes作为节点池, ptr分配节点introot,nodes[N],ptr;intw[N];voidpushup(intu){Node&lson=tr[tr[u].s[0]],&rson=tr[tr[u].s[1]];tr[u].cnt=lson.cnt+rson.cnt+1;tr[u].sum=lson.sum+rson.sum+tr[u].v;tr[u].ls=max(lson.ls,lson.sum+tr[u].v+rson.ls);tr[u].rs=max(rson.rs,rson.sum+tr[u].v+lson.rs);// 注意需要加当前节点的值tr[u].ms=max({lson.ms,rson.ms,lson.rs+tr[u].v+rson.ls});}voidpushdown(intu){Node&lson=tr[tr[u].s[0]],&rson=tr[tr[u].s[1]];if(tr[u].same){tr[u].same=tr[u].rev=0;if(tr[u].s[0]){lson.same=1;lson.v=tr[u].v;lson.sum=tr[u].v*lson.cnt;if(tr[u].v>0)lson.ms=lson.ls=lson.rs=lson.sum;else{lson.ms=tr[u].v;lson.ls=lson.rs=0;}}if(tr[u].s[1]){rson.same=1;rson.v=tr[u].v;rson.sum=tr[u].v*rson.cnt;if(tr[u].v>0)rson.ms=rson.ls=rson.rs=rson.sum;else{rson.ms=tr[u].v;rson.ls=rson.rs=0;}}}// 当子树的根被打上标记, 约定翻转, 这里就不需要翻转elseif(tr[u].rev){tr[u].rev=0;lson.rev^=1,rson.rev^=1;swap(lson.ls,lson.rs),swap(rson.ls,rson.rs);swap(lson.s[0],lson.s[1]),swap(rson.s[0],rson.s[1]);}}voidrotate(intx){inty=tr[x].p,z=tr[y].p;intk=tr[y].s[1]==x;tr[z].s[tr[z].s[1]==y]=x,tr[x].p=z;tr[y].s[k]=tr[x].s[k^1],tr[tr[x].s[k^1]].p=y;tr[x].s[k^1]=y,tr[y].p=x;pushup(y),pushup(x);}voidsplay(intx,intk){while(tr[x].p!=k){inty=tr[x].p,z=tr[y].p;if(z!=k){if((tr[z].s[1]==y)^(tr[y].s[1]==x))rotate(x);elserotate(y);}rotate(x);}if(!k)root=x;}// 将一段序列构建二叉树intbuild(intl,intr,intp){intmid=l+r>>1;intu=nodes[ptr--];tr[u].init(w[mid],p);if(l<mid)tr[u].s[0]=build(l,mid-1,u);if(r>mid)tr[u].s[1]=build(mid+1,r,u);pushup(u);returnu;}intget_k(intk){intu=root;while(u){pushdown(u);intcnt=tr[tr[u].s[0]].cnt+1;if(cnt>k)u=tr[u].s[0];elseif(cnt==k)returnu;elseu=tr[u].s[1],k-=cnt;}return0;}// 内存回收voidrelease(intu){if(tr[u].s[0])release(tr[u].s[0]);if(tr[u].s[1])release(tr[u].s[1]);nodes[++ptr]=u;}intmain(){ios::sync_with_stdio(false);cin.tie(0);// 所有点是可用的for(inti=1;i<N;++i)nodes[++ptr]=i;cin>>n>>m;for(inti=1;i<=n;++i)cin>>w[i];// 为了保证数列时刻都有数字以及如果当前节点没有左右儿子节点不会造成影响tr[0].ms=w[0]=w[n+1]=-INF;// 原序列初始化为树root=build(0,n+1,0);string op;while(m--){cin>>op;if(op=="INSERT"){intposi,tot;cin>>posi>>tot;intu=get_k(posi+1),v=get_k(posi+2);splay(u,0),splay(v,u);for(inti=0;i<tot;++i)cin>>w[i];tr[v].s[0]=build(0,tot-1,v);pushup(v),pushup(u);}elseif(op=="DELETE"){intposi,tot;cin>>posi>>tot;intu=get_k(posi),v=get_k(tot+posi+1);splay(u,0),splay(v,u);release(tr[v].s[0]);tr[v].s[0]=0;pushup(v),pushup(u);}elseif(op=="MAKE-SAME"){intposi,tot,c;cin>>posi>>tot>>c;intu=get_k(posi),v=get_k(tot+posi+1);splay(u,0),splay(v,u);Node&son=tr[tr[v].s[0]];son.same=1;son.v=c;son.sum=son.cnt*c;if(c>0)son.ms=son.ls=son.rs=son.sum;else{son.ms=c;son.ls=son.rs=0;}pushup(v),pushup(u);}elseif(op=="REVERSE"){intposi,tot;cin>>posi>>tot;intu=get_k(posi),v=get_k(tot+posi+1);splay(u,0),splay(v,u);Node&son=tr[tr[v].s[0]];son.rev^=1;swap(son.ls,son.rs);swap(son.s[0],son.s[1]);pushup(v),pushup(u);}elseif(op=="GET-SUM"){intposi,tot;cin>>posi>>tot;intu=get_k(posi),v=get_k(tot+posi+1);splay(u,0),splay(v,u);cout<<tr[tr[v].s[0]].sum<<'\n';pushup(v),pushup(u);}else{cout<<tr[root].ms<<'\n';}}return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/3 1:20:52

易语言流程控制:让程序“智能决策”与“重复执行”

易语言流程控制&#xff1a;让程序“智能决策”与“重复执行” &#x1f3af; 1.4.1 学习目标 &#x1f3af; 作为承上启下的核心章节&#xff08;承接1.3的数据处理基础&#xff0c;开启模块化/批量处理能力&#xff09;&#xff0c;你将通过本节掌握程序的“思维逻辑”&#…

作者头像 李华
网站建设 2026/3/30 6:21:34

全域众链AI + 实体的落地,五大维度印证可行性

在 “AI 实体经济” 的赛道中&#xff0c;不少项目因 “模式悬浮、技术脱节、落地困难” 沦为概念炒作。而全域众链之所以能从众多平台中脱颖而出&#xff0c;核心在于其可行性经过了市场、模式、技术、落地、政策的多重验证 —— 它不是停留在 PPT 上的商业构想&#xff0c;而…

作者头像 李华
网站建设 2026/3/30 10:17:54

揭秘Azure量子开发核心考点:如何7天高效通过MCP认证?

第一章&#xff1a;MCP Azure 量子开发认证概述Azure 量子开发认证&#xff08;Microsoft Certified: Azure Quantum Developer Associate&#xff0c;简称 MCP Azure 量子开发认证&#xff09;是微软为专业开发者设计的一项高级技术认证&#xff0c;旨在验证开发者在 Azure Qu…

作者头像 李华
网站建设 2026/3/30 21:16:58

解锁3D创作新姿势:多视角AI建模实战指南

解锁3D创作新姿势&#xff1a;多视角AI建模实战指南 【免费下载链接】Hunyuan3D-2mv Hunyuan3D-2mv是由腾讯开源的先进3D生成模型&#xff0c;基于Hunyuan3D-2优化&#xff0c;支持多视角图像控制的高质量3D资产生成。它采用扩散模型技术&#xff0c;能够根据用户提供的正面、侧…

作者头像 李华
网站建设 2026/3/31 2:23:18

Wan2.2-T2V-A14B模型对物理定律遵循程度的实证研究

Wan2.2-T2V-A14B模型对物理定律遵循程度的实证研究 在影视预演只需几分钟、广告创意一键生成的今天&#xff0c;我们不禁要问&#xff1a;这些AI生成的视频里&#xff0c;那个“掉下来的球”真的会像现实世界一样加速下落吗&#xff1f;碰撞时的能量传递是否合理&#xff1f;水…

作者头像 李华