题目描述

请写一个程序,要求维护一个数列,支持以下 6 种操作:
请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格

输入

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

输出

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

样例输入

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

样例输出

-1
10
1
10

提示

这道题的区间操作十分全,无论是用非旋转treap还是splay写,都会有更深入的理解。

讲一下每个操作的实现

1、将插入的数再建一棵treap,然后把原treap断裂,把新建treap合并进去。

2、把treap断裂成三部分,然后再把左右两部分合并。

3、也是把treap断裂成三部分,把中间部分打标记,标记在合并时下传。

4、和上面一样,也是断裂成三部分,中间打标记。

5、断裂成三部分,输出中间部分根节点的子树和。

6、直接输出根节点的最大连续子段和。

最后不要忘了资源回收(回收节点编号)

最后附上代码(有注释)

#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int num;
int pos;
int tot;//树的大小
int root;//根节点
int n,k,g;
int x,y,z;
int b,c,d;
char ch[5];
queue<int>q;//资源回收队列
int a[200010];//插入序列及初始序列
int m[500010];//区间最大子段和
int s[500010];//翻转标记
int f[500010];//修改标记
int r[500010];//随机数
int ls[500010];//左儿子
int rs[500010];//右儿子
int lm[500010];//子树区间中从左端点开始的最大连续子段和
int rm[500010];//子树区间中以右端点结束的最大连续子段和
int val[500010];//节点权值
int sum[500010];//子树区间和
int size[500010];//子树大小
int INF=2147483647;
int insert(int v)
{
int x;
if(!q.empty())
{
x=q.front();
q.pop();
}
else
{
x=++tot;
}
size[x]=1;
ls[x]=rs[x]=s[x]=0;
f[x]=INF;
r[x]=rand();
val[x]=sum[x]=v;
lm[x]=rm[x]=m[x]=v;
return x;
}
void updata(int x)
{
if(!x)
{
return ;
}
size[x]=size[ls[x]]+size[rs[x]]+1;
sum[x]=sum[ls[x]]+sum[rs[x]]+val[x];
m[x]=max(max(0,rm[ls[x]])+val[x]+max(0,lm[rs[x]]),max(m[ls[x]],m[rs[x]]));
lm[x]=max(lm[ls[x]],sum[ls[x]]+val[x]+max(0,lm[rs[x]]));
rm[x]=max(rm[rs[x]],sum[rs[x]]+val[x]+max(0,rm[ls[x]]));
}
void change(int x,int v)
{
val[x]=v;
sum[x]=size[x]*v;
lm[x]=rm[x]=max(0,sum[x]);
m[x]=max(val[x],sum[x]);
f[x]=v;
}
void rotate(int x)
{
swap(ls[x],rs[x]);
swap(lm[x],rm[x]);
s[x]^=1;
}
void downdata(int x)
{
if(s[x])
{
if(ls[x])
{
rotate(ls[x]);
}
if(rs[x])
{
rotate(rs[x]);
}
}
if(f[x]!=INF)
{
if(ls[x])
{
change(ls[x],f[x]);
}
if(rs[x])
{
change(rs[x],f[x]);
}
}
s[x]=0;
f[x]=INF;
}
int build(int l,int r)
{
if(l>r)
{
return 0;
}
int mid=(l+r)>>1;
int v=a[mid];
int x=insert(v);
ls[x]=build(l,mid-1);
rs[x]=build(mid+1,r);
updata(x);
return x;
}
void split(int now,int t,int &x,int &y)
{
if(!now)
{
x=y=0;
}
else
{
downdata(now);
if(t<=size[ls[now]])
{
y=now;
split(ls[now],t,x,ls[now]);
}
else
{
x=now;
split(rs[now],t-size[ls[now]]-1,rs[now],y);
}
updata(now);
}
}
int merge(int x,int y)
{
if(!x||!y)
{
return x+y;
}
downdata(x);
downdata(y);
if(r[x]<r[y])
{
rs[x]=merge(rs[x],y);
updata(x);
return x;
}
else
{
ls[y]=merge(x,ls[y]);
updata(y);
return y;
}
}
void inque(int x)
{
if(!x)
{
return ;
}
q.push(x);
inque(ls[x]);
inque(rs[x]);
}
int main()
{
srand(16);
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
val[0]=m[0]=-INF;
root=build(1,n);
while(k--)
{
scanf("%s",ch);
if(ch[0]=='I')
{
scanf("%d%d",&pos,&num);
for(int i=1;i<=num;i++)
{
scanf("%d",&a[i]);
}
z=build(1,num);
split(root,pos,x,y);
root=merge(merge(x,z),y);
}
else if(ch[0]=='D')
{
scanf("%d%d",&pos,&num);
split(root,pos-1,x,y);
split(y,num,b,c);
root=merge(x,c);
inque(b);
}
else if(ch[2]=='K')
{
scanf("%d%d%d",&pos,&num,&g);
split(root,pos-1,x,y);
split(y,num,b,c);
change(b,g);
root=merge(x,merge(b,c));
}
else if(ch[0]=='R')
{
scanf("%d%d",&pos,&num);
split(root,pos-1,x,y);
split(y,num,b,c);
rotate(b);
root=merge(x,merge(b,c));
}
else if(ch[0]=='G')
{
scanf("%d%d",&pos,&num);
split(root,pos-1,x,y);
split(y,num,b,c);
printf("%d\n",sum[b]);
root=merge(x,merge(b,c));
}
else
{
printf("%d\n",m[root]);
}
}
return 0;
}

BZOJ1500[NOI2005]维修数列——非旋转treap的更多相关文章

  1. bzoj千题计划221:bzoj1500: [NOI2005]维修数列(fhq treap)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 1.覆盖标记用INF表示无覆盖标记,要求可能用0覆盖 2.代表空节点的0号节点和首尾的两个虚拟 ...

  2. [BZOJ1500][NOI2005]维修数列---解题报告

    Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...

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

    Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...

  4. [bzoj1500][NOI2005]维修数列_非旋转Treap

    维修数列 bzoj-1500 NOI-2005 题目大意:给定n个数,m个操作,支持:在指定位置插入一段数:删除一个数:区间修改:区间翻转.查询:区间和:全局最大子序列. 注释:$1\le n_{ma ...

  5. 2018.08.06 bzoj1500: [NOI2005]维修数列(非旋treap)

    传送门 平衡树好题. 我仍然是用的fhqtreap,感觉速度还行. 维护也比线段树splay什么的写起来简单. %%%非旋treap大法好. 代码: #include<bits/stdc++.h ...

  6. BZOJ1500[NOI2005]维修数列

    Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...

  7. splay模板三合一 luogu2042 [NOI2005]维护数列/bzoj1500 [NOI2005]维修数列 | poj3580 SuperMemo | luogu3391 【模板】文艺平衡树(Splay)

    先是维修数列 题解看这里,但是我写的跑得很慢 #include <iostream> #include <cstdio> using namespace std; int n, ...

  8. [bzoj1500][NOI2005]维修数列[Treap][可持久化Treap]

    非旋转式Treap1500 :) #include <bits/stdc++.h> #pragma GCC optimize(3) using namespace std; const i ...

  9. BZOJ1500 [NOI2005]维修数列-fhq_Treap

    题面见这里 反正是道平衡树,就拿 fhq_Treap 写了写... 这道题思路基本是围绕“用 Treap 维护中序遍历” 和 中序遍历的性质 来进行的操作 所以就可以类比线段树进行一些操作 1. 建树 ...

随机推荐

  1. MySQL(四)字段及常用函数

    一.字段 数据库表中的每一行叫做一个“记录”,每一个记录包含这行中的所有信息,但记录在数据库中并没有专门的记录名,常常用它所在的行数表示这是第几个记录. 在数据库中存放在表行列交叉处的数据叫做“值”, ...

  2. 【C语言】结构体占用字节数及存储与空间分配

    我们都知道在数据类型中,char类型占1个字节,short占2个字节,int占4个字节,long占8个字节等等. 在计算结构体大小时需要考虑其内存布局,结构体在内存中存放是按单元存放的,每个单元多大取 ...

  3. React基础篇 - 02.JSX 简介

    JSX 简介 请观察下面的变量声明: const element = <h1>Hello, world!</h1>; 这种看起来可能有些奇怪的标签语法既不是字符串也不是HTML ...

  4. POI Sax 事件驱动解析Excel2003文件

    POI事件驱动解析Excel文件 package com.boguan.bte.util.excel; import java.io.FileInputStream; import java.io.I ...

  5. kafka学习2:kafka集群安装与配置

    在前一篇:kafka学习1:kafka安装 中,我们安装了单机版的Kafka,而在实际应用中,不可能是单机版的应用,必定是以集群的方式出现.本篇介绍Kafka集群的安装过程: 一.准备工作 1.开通Z ...

  6. EZ 2018 06 10 NOIP2018 模拟赛(十八)

    好久没写blog&&比赛题解了,最近补一下 这次还是很狗的,T3想了很久最后竟然连并查集都忘写了,然后T2map莫名爆炸. Rating爆减......链接不解释 好了我们开始看题. ...

  7. 学习ML.NET(2): 使用模型进行预测

    训练模型 在上一篇文章中,我们已经通过LearningPipeline训练好了一个“鸢尾花瓣预测”模型, var model = pipeline.Train<IrisData, IrisPre ...

  8. 老生常谈,函数柯里化(curring)

    柯里化这个概念确实晦涩难懂,没有深入思考过的人其实真的很难明白这是一个什么东西.看起来简单.简单到或许只需要一行代码: const curry = fn => (…args) => fn. ...

  9. mysql 通过慢查询日志查写得慢的sql语句

    MySQL通过慢查询日志定位那些执行效率较低的SQL 语句,用--log-slow-queries[=file_name]选项启动时,mysqld 会写一个包含所有执行时间超过long_query_t ...

  10. Scrum与看板区别

    看板:在制品(work-in-progress, WIP)必须被限制 WIP上限和拉动式生产   1. Scrum与看板简述 Scrum:组织拆分,工作拆分,开发时间拆分,优化发布计划,过程优化 看板 ...