[BZOJ1500]NOI2005 维修数列|splay

NOI2005维护数列原题 维护数列 【问题描述】 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1. 插入 INSERT_posi_tot_c1_c2_..._ctot 在当前数列的第posi 个数字后插入tot 个数字:c1, c2, …, ctot;若在数列首插 入,则 posi 为 0 2. 删除 DELETE_posi_tot 从当前数列的第 posi 个数字开始连续 删除 tot 个数字 3. 修改 MAKE-SAME_posi_tot_c 将当前数列的第 posi 个数字开始的连 续 tot 个数字统一修改为 c 4. 翻转 REVERSE_posi_tot 取出从当前数列的第 posi 个数字开始 的 tot 个数字,翻转后放入原来的位置 5. 求和 GET-SUM_posi_tot 计算从当前数列开始的第 posi 个数字 开始的 tot 个数字的和并输出 6. 求和最 大的子列 MAX-SUM 求出当前数列中和最大的一段子列, 并输出最大和 立即下载

这题号称是noi出过最变态的数据结构题,,感觉还差不多嘛。。一开始我一直在纠结splay上的节点一点要有一个key值的啊,要是以这个数在序列中的位置作为key值的话又要插入又要删除肯定弄不了。。然后想了很久突然顿悟。。貌似我给一个初始顺序以后是不用访问key的&&找第k位的数只要写一个findkth就行了嘛。。(当时太弱)

然后我就一口气写了下来。。

对每个节点维护size,sum,maxsum,maxpre,maxpos(这两个用于更新maxsum),same,rev(这两个是lazy标记)。

更新maxsum考虑3种情况,一是左儿子的maxsum,二是右儿子的maxsum,三是左儿子的maxpos+自身num+右儿子maxpre,这里maxpre和maxpos更新的时候是可以一个都不要也就是为0的,我就在这里被坑了。。

1.      初始或者插入的时候建树用类似线段树的二分的方法,然后把pos转到root,把pos+1转到root下,只要把数挂在pos+1的左儿子下就行了。。这里有一个关于findkth的问题,为了方便处理边界我一开始插入了一个头结点和一个尾结点,findkth的时候要小心头结点的存在。。

2.      删除的时候把pos转到root,pos+tot+1转到root下,pos+tot+1的左儿子就是要删除的区间,直接删去即可。。这里要注意一个回收内存的问题,要把删去的结点放到一个栈里,newnode的时候优先从这个栈里拿结点,这样既可以节省内存又可以节省时间。。

3.      修改和翻转的时候找出区间打上标记就行。

4.      getsum找出区间直接输出答案,maxsum直接输出root的答案。

打到这里最原始的程序就写完了,但是我一开始在处理标记的时候只是单纯的打上标记没有更新维护的东西,导致每次输出答案必须遍历子树更新答案,时间复杂度没有了保证。。然后我看黄学长的代码发现打标记的时候要把信息及时维护一下,一加上去速度瞬间就快了起来。。(当时太弱)

第二个坑点是一开始插入的头结点尾结点的值要是-inf不能是0,否则maxsum更新时会出错。。

最后就是same标记的问题,要特殊处理一下makesame(0)的情况。。

到这里就搞定了,6052MSAC,有点慢。。

#include<iostream>
#include<cstdio>
#include<memory.h>
using namespace std;
const int inf=99999999,maxn=500005;
int n,m,i,nnode=0,rest=0,root=0,root1,pos,tot,k,q[maxn],c[maxn][2],size[maxn],pre[maxn],num[maxn],maxsum[maxn],maxpre[maxn],maxpos[maxn],same[maxn],rev[maxn],sum[4000005],s[maxn];
char str[10];
void update(int x)
{
	size[x]=size[c[x][0]]+size[c[x][1]]+1;sum[x]=sum[c[x][0]]+sum[c[x][1]]+num[x];
	maxsum[x]=max(max(maxsum[c[x][0]],maxsum[c[x][1]]),maxpos[c[x][0]]+num[x]+maxpre[c[x][1]]);
	maxpre[x]=max(sum[c[x][0]]+maxpre[c[x][1]]+num[x],maxpre[c[x][0]]);maxpos[x]=max(sum[c[x][1]]+maxpos[c[x][0]]+num[x],maxpos[c[x][1]]);
}

void marksame(int x,int c)
{
	same[x]=c;
	if (c==1001) c=0;
	num[x]=c;sum[x]=size[x]*c;
	if (c>=0) maxsum[x]=maxpre[x]=maxpos[x]=size[x]*c; else maxpre[x]=maxpos[x]=0,maxsum[x]=c;
}
void markrev(int x)
{
	swap(c[x][0],c[x][1]);
	swap(maxpre[x],maxpos[x]);
	rev[x]^=1;
}
void down(int x)
{
	if (same[x])
	{
		if (c[x][0]) marksame(c[x][0],same[x]); if (c[x][1]) marksame(c[x][1],same[x]);
		same[x]=0; 
	}
	if (rev[x])
	{
		if (c[x][0]) markrev(c[x][0]);if (c[x][1]) markrev(c[x][1]);
		rev[x]=0;
	}
}
void newnode(int &x,int fa,int k)
{
	if (rest) x=s[rest--];else x=++nnode;
	pre[x]=fa;num[x]=k;	size[x]=1;
	c[x][0]=c[x][1]=same[x]=rev[x]=0;
	sum[x]=maxsum[x]=k;
	maxpre[x]=maxpos[x]=max(k,0);
}
void rot(int x,int kind)
{
	int y=pre[x];int z=pre[y];down(x);
	c[y][!kind]=c[x][kind];pre[c[x][kind]]=y;
	c[x][kind]=y;pre[y]=x;
	pre[x]=z;if (z) c[z][c[z][1]==y]=x;
	update(y);update(x);if (z) update(z);
}
void splay(int x,int goal)
{
	int y,z,kind;
	while (pre[x]!=goal)
	{
		y=pre[x];down(y);
		if (pre[y]==goal) rot(x,c[y][0]==x);
		else
		{
			z=pre[y];down(z);kind=c[z][0]==y;
			if (c[y][!kind]==x) rot(y,kind);else rot(x,!kind);
			rot(x,kind);
		}
	}
	if (goal==0) root=x;
}
int findkth(int x,int k)//加处理 
{
	down(x);
	if (size[c[x][0]]>=k) return findkth(c[x][0],k);
	if (k==size[c[x][0]]+1) return x;
	if (k>size[c[x][0]]+1) return findkth(c[x][1],k-size[c[x][0]]-1);
}
void build(int &x,int fa,int l,int r)
{
	if (l>r) return;
	int mid=(l+r)/2;
	newnode(x,fa,q[mid]);
	if (l==r) return;
	build(c[x][0],x,l,mid-1);build(c[x][1],x,mid+1,r);
	update(x);
}
void insert(int pos,int tot)
{
	int i;
	for (i=1;i<=tot;i++)
		scanf("%d",&q[i]);
	build(root1,0,1,tot);
	splay(findkth(root,pos+1),0);
	splay(findkth(root,pos+2),root);
	c[c[root][1]][0]=root1;pre[root1]=c[root][1];
	update(c[root][1]);update(root);
}
void erase(int x)
{
	if (!x) return;
	s[++rest]=x;
	erase(c[x][0]);erase(c[x][1]);
}
void deleted(int pos,int tot)
{
	splay(findkth(root,pos),0);splay(findkth(root,pos+tot+1),root);
	erase(c[c[root][1]][0]);
	c[c[root][1]][0]=0;
	update(c[root][1]);update(root);
}
void makesame(int pos,int tot,int k)
{
	if (k==0) k=1001;
	splay(findkth(root,pos),0);splay(findkth(root,pos+tot+1),root);
	marksame(c[c[root][1]][0],k);
	update(c[root][1]);update(root);
}
void markrev(int pos,int tot)
{
	splay(findkth(root,pos),0);splay(findkth(root,pos+tot+1),root);
	markrev(c[c[root][1]][0]);
	update(c[root][1]);update(root);
	
}
int getsum(int pos,int tot)
{
	splay(findkth(root,pos),0);splay(findkth(root,pos+tot+1),root);
	return sum[c[c[root][1]][0]];
}
void print(int x)
{
	if (c[x][0]) print(c[x][0]);
	printf("%d->num:%d,fa:%d,lc:%d,rc:%d,size:%d,sum:%d,maxpre:%d,maxpos:%d,maxsum:%d,same:%d,rev:%d\n",x,num[x],pre[x],c[x][0],c[x][1],size[x],sum[x],maxpre[x],maxpos[x],maxsum[x],same[x],rev[x]);
	if (c[x][1])print(c[x][1]);
}
int main()
{
	freopen("shulie.in","r",stdin);
	freopen("my.out","w",stdout);
	scanf("%d%d",&n,&m);
	newnode(root,0,-inf);newnode(c[root][1],root,-inf);
	insert(0,n);
	size[0]=pre[0]=same[0]=rev[0]=num[0]=sum[0]=maxpre[0]=maxpos[0]=0;maxsum[0]=-inf;
	for (i=1;i<=m;i++)
	{
		scanf("%s",&str);
		if (str[2]!='X') scanf("%d%d",&pos,&tot); else printf("%d\n",maxsum[root]);
		if (str[0]=='I') insert(pos,tot);
		if (str[0]=='D') deleted(pos,tot);
		if (str[0]=='M'&&str[2]=='K') scanf("%d",&k),makesame(pos,tot,k);
		if (str[0]=='R') markrev(pos,tot);
		if (str[0]=='G') printf("%d\n",getsum(pos,tot));
	}
}


iTunes登录协议抓包实战:绕过反检测与TLS解密的完整方案 在软件逆向与网络协议分析中,抓包工具扮演着关键角色。代理型工具如Fiddler通过修改系统代理实现HTTPS解密,而驱动型工具如HTTPDebugger则注入进程钩取网络API,但这些实现机制往往会被具有反检测策略的客户端识别。以iTunes登录协议为例,其内置证书锁定、进程完整性与系统代理检测等防护,导致常规抓包方案失效。从工具原理出发,对比不同抓包方案的暴露面,重点介绍如何利用Fiddler通过中间人代理获取明文流量,以及使用Wireshark进行被动监听规避检测的进阶技巧,并总结常见问题排查经验,为分 阅读详情

相关推荐

逆向解析手淘x-sign签名算法:从抓包到API调用的完整实践

本文详细解析了手淘x-sign签名算法的逆向过程,从抓包工具选择到API调用实践,提供了完整的解决方案。通过分析签名参数组成和生成机制,帮助开发者理解并实现淘宝接口的合法调用,同时强调了安全与合规的重要性。

weixin_29323273的博客 606

P2042 [NOI2005]维护数列 splay

学块状链表的时候找到的这个题,看了大佬的思路发现splay真香,块状链表虽然好理解,但写起来真的有点烦。 P2042 [NOI2005]维护数列 对一个数列进行插入,删除,修改(统一置为某数),区间翻转,区间求和,整体最大子列和。 用splay维护序列的基本操作:先通过旋转把要操作的区间单独拎出来,比如要操作从k开始的tot个数,那就先把下标k-1对应的结点转到整棵树的根,然后把k+tot转到根的...

haiku的博客 286

《Sigrity SystemSI 2023+LPDDR4仿真自学笔记》(一)创建工程(Part1)

为了加强SystemSI 2023软件的熟悉度,咱们完整的走一个仿真全流程。

weixin_45199544的博客 6334

【bzoj1500】[NOI2005]维修数列 Splay

终于打败大boss了,耗时一下午。 应该是splay维护序列题型的巅峰了吧。 这道题不能单纯的开点,因为会MLE,所以要用回收节点的过程。 说一下搞法吧: 1、插入,提取区间,递归建树 2、删除,提取区间,把删去的点用一个栈储存下来 3、修改,提取区间,打个标记 4、翻转,提取区间,打个标记 5、求和、最大连续子段和,维护一下就可以了。 WA点: 这道题不用开longlong,

Oxer的专栏 2384

别再为授权费头疼了!手把手教你免授权搞定西门子、马扎克等12种主流数控机床的数据采集

本文提供了一套免授权采集西门子、马扎克等12种主流数控机床数据的实战指南,帮助中小型机加工车间节省80%以上的采集成本。通过TCP/UDP协议逆向工程和跨平台数据整合,实现经济、灵活且可持续的数据采集方案,涵盖设备兼容性处理、数据频率优化等关键问题。

weixin_26873711的博客 709

PCI-Express、MiniPCIe、ExpressCard接口转换说明/引脚互换关系

通过引脚PIN互换可以在PCI-Express、MiniPCIe、ExpressCard之间切换不同的接口;提供接口引脚表和标准尺寸图。

tech34的博客 7124

bzoj1500 [NOI2005]维修数列解题报告

Bzoj 1500: [NOI2005]维修数列 解题报告 题目原文 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 10429  Solved: 3218 [Submit][Status][Discuss] Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数

ACoder 2728

YOLOv8 TensorRT C++部署实战详解:从XMake构建到推理流水线

本项目实现了一个基于YOLOv8和TensorRT的高性能火灾烟雾检测系统,具有以下核心特点: 技术架构:采用TensorRT 8.6+进行GPU加速推理,结合CUDA 12.1和OpenCV 4.8+,实现高效计算机视觉处理。系统使用XMake替代CMake构建,配置更简洁高效。

hscing的博客 1065

BZOJ1500 [NOI2005] 维修数列 (含数据生成器)

qwq据popoqqq说这是初学者噩梦级别的题目,有点怕。

QWsin的博客 1452

慕课软件质量保证与测试(习题集)

慕课金陵科技学院.软件质量保证与测试.期末复习.习题汇总0 总目录1 绪论1.1 软件质量保证与测试的产生与发展1.2 软件缺陷,软件错误,软件故障1.3 软件质量保证与测试的意义,原则和挑战1.4 单元测试1.5 课后作业2 软件测试策略2.1 软件测试的模型,过程和生命周期2.2 软件测试的方法和技术2.3 单元测试2.4 课后作业3 黑盒测试3.1 黑盒测试概述3.2 等价类划分测试3.3 边界值测试3.4 错误推测法3.5 判定表驱动法3.6 因果图法3.7 场景法3.8 正交实验法3.9 单元测试

weixin_42473228的博客 5万+

安装西门子TIA Portal V15.1提示先决条件不足如何处理?

安装TIA Portal STEP 7 Professional WinCC Professional V15.1提示先决条件不足,需要如何才能够满足安装条件呢? 1.硬件要求: 安装 STEP 7 Basic / Professional V15.1 的计算机必须至少满足以下需求: 处理器: Core i5-6440EQ 3.4 GHz 或者相当 内存: 16GB或者更多(对于大型项目,为32GB) 硬盘:SSD,配备至少50GB的存储空间 图形分辨率:最小 1920 x 1080 显示器:15.6"

Robot_PLC_HMI_Automation 2万+

BZOJ1500: [NOI2005]维修数列 Splay

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 12862  Solved: 4104 [Submit][Status][Discuss] 题解: Splay的巅峰之作,支持插入一堆数,删除一堆数,区间反转,区间权值覆盖,求和,求最大子序列 对于插入和删除: 因为内存只能开到500000,

Oakley 640

三臂杆大型液压机械臂集中式ADRC控制系统设计

本文设计了一种用于三臂杆液压机械臂的集中式自抗扰控制(ADRC)系统。该系统通过建立包含惯性矩阵、科氏力、重力及摩擦力的非线性动力学模型,并集成液压系统传递函数,构建了完整的系统模型。控制方案采用跟踪微分器安排过渡过程,扩张状态观测器实时估计系统状态和总扰动,以及非线性状态误差反馈生成控制量。MATLAB实现展示了集中式ADRC控制器的核心结构,包括参数定义、跟踪微分器、扩张状态观测器和非线性反馈模块的设计。该系统能有效处理多关节耦合效应,实现三输入三输出的MIMO控制,具有抗干扰能力强、响应速度快的特点。

huanghm88的专栏 271

Splay 模板【NOI2005】 bzoj1500 维修数列

老师说写博客有助于学习和理解代码,所以从今天起,做一个写博客的人,面朝代码,春暖花开o(n_n)o。 Splay是一种可以对一个数列进行区间修改,区间反转,查询最值,查询总和等操作的数据结构(我觉得Splay的结构类似于treap,功能类似于线段树),而且能够快速实现区间的分裂与合并。 Splay与Treap的最大区别是旋转方式,Treap将树按照堆得形式维护,只需要单旋。而S

Todobe 552

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【splay】BZOJ 1500: [NOI2005]维修数列

BZOJ 3224 普通平衡树DescriptionInput输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。Output对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。Sample Input9 8 2 -6 3 5 1

puck_just_me的blog 786

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

bzoj 1500: [NOI2005]维修数列 splay

1500: [NOI2005]维修数列 Time Limit:10 SecMemory Limit:64 MBSubmit:6556Solved:1963[Submit][Status] Description Input 输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的...

alex151194310的博客 170

[bzoj1500][NOI2005]维修数列 splay大模板

写了后就 需重写

Unlimited Code Works 298

【BZOJ1500】【NOI2005】维修数列(Splay)

【BZOJ1500】【NOI2005】维修数列(Splay) 题面 不想再看见这种毒瘤题,自己去BZOJ看 题解 Splay良心模板题 真的很简单 我一言不发 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #i...

weixin_30412167的博客 82

BZOJ 1500 [NOI2005]维修数列 Splay

Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。 第2行包含N个数字,描述初始时的数列。 以下M行,每行一条命令,格式参见问题描述中的表格。 任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。 插入的数字总数不超过4 000

I'm Growing 547

[BZOJ1500][NOI2005]维修数列 解题报告 Splay

  Portal Gun:[BZOJ1500][NOI2005]维修数列   有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了   关于这道题...该说什么好呢...网上好多人评论这道题又是难啊,又是要调很久什么的,还讲这是道平衡树的boos级别的题...看了题后,好像也没有说的这么难吧,思路比较简单,代码也不...

weixin_30794491的博客 75

[BZOJ1500][NOI2005][Splay]维修数列

[Problem Description] [Data Structure] Splay [Analysis] Splay没话说,维护节点信息和pushdown,update与线段树有些像。 [Pay Attention] 这里有一个逗比的地方,MAX-SUM不包括空串这种情况,也就是说,就算序列里面最大的数是负数,也不能输出0,而是输出那个负数。 [Code] /**

gaotianyu1350的专栏 748

【BZOJ】1500 [NOI2005]维修数列 【splay】

传送门:【BZOJ】1500 [NOI2005]维修数列

poursoul 963

[NOI2005] [BZOJ1500] 维修数列 - splay

前段日子一直在看LCT QWQ。照着板子A了魔法森林但是感觉还是不是太明白,神犇告诉我说应该先把splay学好然后码了几天找了N处错误才A了这题     splay大模板题啊。虽然程序跑得不很快,但是总算AC了qwq。 注释里面有一些提示,就是我错的地方qwq,提醒大家注意哈。     #include "algorithm" #include "iostream" #include "std

whzzt的博客 613

【BZOJ1500】[NOI2005]维修数列【Splay】

http://www.lydsy.com/JudgeOnline/problem.php?id=1500 这神题终于过了... 主要是: find()那里少写了一个pushdown()。 辣鸡回收写跪了。 /* Footprints In The Blood Soaked Snow */ #include #include using namespace s

BraketBN 490

bzoj 1500 NOI2005 维修数列 [Splay]

维修数列Time Limit: 10 Sec Memory Limit: 64 MB Submit: 11839 Solved: 3724Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。 第2行包含N个数字,描述初始时的数列。 以下M行,每行一条命令,格式参见问题描述中的表格。 任何时刻

C'est la vie. 573

[BZOJ1500][NOI2005]维修数列(splay)

题目描述传送门题解splay模板题(笑 这题是我今年1月左右看到的。记得当时只调过了样例然后交上去过了一个点就用了我一天的时间。果然我还是太傻逼。 填上了好大一个坑。 前5个都是splay的基础操作,就是第6个比较麻烦。因为要维护区间最大连续子序列和,可以维护3个值:Max子树最大连续子序列和,maxl子树自左端起最大连续子序列和,maxr子树自右端起最大连续子序列和。注意这里的Max是不允许

zyf2000 1010
上一篇: [BZOJ1833]ZJOI2010 数字计数|数位DP
下一篇: [BZOJ1834]ZJOI2010网络扩容|最大流|费用流
Tag_king
博客等级 码龄12年 15粉丝 164原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值