题目描述

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

输入输出格式

输入格式:

输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M 表示要进行的操作数目。 第 2 行包含 N 个数字,描述初始时的数列。 以下 M 行,每行一条命令,格式参见问题描述中的表格

输出格式:

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

输入输出样例

输入样例#1:

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:

-1

10

1

10

说明

你可以认为在任何时刻,数列中至少有 1 个数。

输入数据一定是正确的,即指定位置的数在数列中一定存在。

50%的数据中,任何时刻数列中最多含有 30 000 个数;

100%的数据中,任何时刻数列中最多含有 500 000 个数。

100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。

100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 。

分析

复杂度 思维1 编程7

本题思维上很简单,先判断使用平衡树,再用ls,rs维护最大和,之后挨个完成各个功能。注意节点需要回收利用。回收总复杂度O(n)。总体复杂度O(nlogn)。

代码

#include <cstdio>
#include <cstdlib>
#define rt ch[0][0]
const int N=500000,S=N+100,inf=(1<<25)-1;
int n,m,a[S],bin[S],ch[S][2],ls[S],rs[S],fa[S],su[S],sz[S],mx[S],add[S],rev[S];
void rd(int &x)
{
x=0;char c=getchar(),t=1;
while (c!='-' && (c<'0' || c>'9')) c=getchar();
if (c=='-') t=-1,c=getchar();
while (c>='0' && c<='9') x=(x<<3)+(x<<1)+(c-'0'),c=getchar();
x*=t;
}
void init()
{
for (int i=0;i<=N;i++)
bin[i]=i;
bin[0]=1; rt=1; ls[0]=rs[0]=mx[0]=-inf;
sz[0]=0; bin[0]=2;//use 1
sz[1]=2;ch[1][1]=2;fa[1]=0;a[1]=-inf;add[1]=inf; bin[0]=3;//use 2
sz[2]=1;fa[2]=1;add[2]=inf;a[2]=-inf;
}
inline int ma(int a,int b){if (a>b) return a;return b;}
inline int ma3(int a,int b,int c){return ma(a,ma(b,c));}
inline void swap(int &a,int &b){a^=b^=a^=b;}
inline void up(int x)
{
int L=ch[x][0],R=ch[x][1];
sz[x]=sz[L]+sz[R]+1;
su[x]=su[L]+su[R]+a[x];
ls[x]=ma3(ls[L],su[L]+a[x],su[L]+a[x]+ls[R]);
rs[x]=ma3(rs[R],su[R]+a[x],su[R]+a[x]+rs[L]);
int mid=ma(rs[L],0)+a[x]+ma(ls[R],0);
mx[x]=ma3(mx[L],mx[R],mid);
mx[x]=ma3(mx[x],ls[x],rs[x]);
}
inline void down(int x)
{
int &L=ch[x][0],&R=ch[x][1];
if (rev[x])
{
if (L)
{
rev[L]^=1;
swap(ch[L][0],ch[L][1]);
swap(ls[L],rs[L]);
}
if (R)
{
rev[R]^=1;
swap(ch[R][0],ch[R][1]);
swap(ls[R],rs[R]);
}
rev[x]=0;
}
if (add[x]!=inf)
{
if (L)
{
add[L]=add[x];
su[L]=add[L]*sz[L];
a[L]=add[L];
if (add[x]>0)
ls[L]=rs[L]=mx[L]=su[L];
else
ls[L]=rs[L]=mx[L]=a[L];
}
if (R)
{
add[R]=add[x];
su[R]=add[R]*sz[R];
a[R]=add[R];
if (add[x]>0)
ls[R]=rs[R]=mx[R]=su[R];
else
ls[R]=rs[R]=mx[R]=a[R];
}
add[x]=inf;
}
}
inline bool lor(int x){return ch[fa[x]][1]==x;}
inline void link(int x,int fat,int o){fa[x]=fat;ch[fat][o]=x;}
inline void rotate(int x)
{
int y=fa[x],r=fa[y];
down(y);down(x);
int rson=lor(y),yson=lor(x);
link(ch[x][yson^1],y,yson);
link(y,x,yson^1);
link(x,r,rson);
up(y);up(x);
}
void splay(int x,int to)
{
to=fa[to];
while (fa[x]!=to)
{
if (fa[fa[x]]==to) rotate(x);
else if (lor(x)==lor(fa[x])) rotate(fa[x]),rotate(x);
else rotate(x),rotate(x);
}
}
void build(int &k,int fat,int l,int r)
{
if (l>r)
{
k=0;
return;
}
k=bin[bin[0]++];
fa[k]=fat;
int mid=(l+r)>>1;
build(ch[k][0],k,l,mid-1);
rd(a[k]);
add[k]=inf;rev[k]=0;
build(ch[k][1],k,mid+1,r);
up(k);
}
void recycle(int k)
{
if (!k) return;
recycle(ch[k][0]);
a[k]=su[k]=ls[k]=rs[k]=mx[k]=fa[k]=add[k]=rev[k]=0;
bin[--bin[0]]=k;
recycle(ch[k][1]);
ch[k][0]=ch[k][1]=0;
}
int find(int x)
{
int o=rt;
while (o)
{
down(o);
if (sz[ch[o][0]]+1==x)
break;
if (x<=sz[ch[o][0]])
o=ch[o][0];
else x-=sz[ch[o][0]]+1,o=ch[o][1];
}
return o;
}
void insert(int pos,int tot)
{
pos++;
int bg=find(pos),ed=find(pos+1);
splay(bg,rt);
splay(ed,ch[bg][1]);
build(ch[ed][0],ed,1,tot);
up(ed);up(bg);
}
void del(int pos,int tot)
{
int bg=find(pos),ed=find(pos+tot+1);
splay(bg,rt);splay(ed,ch[bg][1]);
recycle(ch[ed][0]);
ch[ed][0]=0;
up(ed);up(bg);
}
void make_same(int pos,int tot,int x)
{
int bg=find(pos),ed=find(pos+tot+1);
splay(bg,rt);splay(ed,ch[bg][1]);
int o=ch[ed][0];
add[o]=x;su[o]=x*sz[o];a[o]=x;
if (x>0) ls[o]=rs[o]=mx[o]=su[o];
else ls[o]=rs[o]=mx[o]=a[o];
up(ed);up(bg);
}
void reverse(int pos,int tot)
{
int bg=find(pos),ed=find(pos+tot+1);
splay(bg,rt);splay(ed,ch[bg][1]);
down(bg);down(ed);
int o=ch[ed][0];
rev[o]=1;
swap(ch[o][0],ch[o][1]);
swap(ls[o],rs[o]);
up(ed);up(bg);
}
void getsum(int pos,int tot)
{
int bg=find(pos),ed=find(pos+tot+1);
splay(bg,rt);
splay(ed,ch[bg][1]);
int o=ch[ed][0];
printf("%d\n",su[o]);
}
int main()
{
rd(n);rd(m);
init();
build(ch[2][0],2,1,n);up(2);up(1);
char op[10];int tot,pos,x;
while (m--)
{
scanf("%s",op);
if (op[2]=='X')//max_sum
printf("%d\n",mx[rt]);
else
{
rd(pos);rd(tot);
if (op[2]=='S')//Insert
insert(pos,tot);
else if (op[2]=='L')
del(pos,tot);
else if ('K'==op[2])
{
scanf("%d",&x);
make_same(pos,tot,x);
}
else if ('V'==op[2])
reverse(pos,tot);
else getsum(pos,tot);
}
}
return 0;
}

Luogu P2042 [NOI2005]维护数列的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. P2042 [NOI2005]维护数列

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

  8. [NOI2005]维护数列(区间splay)

    [NOI2005]维护数列(luogu) 打这玩意儿真是要了我的老命 Description 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文 ...

  9. 数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列

    339. [NOI2005] 维护数列 时间限制:3 s   内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际 ...

随机推荐

  1. Delphi 格式化函数 Format函数

    function Format(const Format: string; const Args: array of const): string; function Format(const For ...

  2. PHP curl_multi_info_read函数

    curl_multi_info_read — 获取当前解析的cURL的相关传输信息 说明 array curl_multi_info_read ( resource $mh [, int &$ ...

  3. vue常见面试题

    什么是 mvvm? MVVM 是 Model-View-ViewModel 的缩写.mvvm 是一种设计思想.Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑:View ...

  4. nginx调优配置

    nginx调优配置 user www www; #工作进程:数目.根据硬件调整,通常等于CPU数量或者2倍于CPU. worker_processes 8; worker_cpu_affinity 0 ...

  5. Angular项目中迭代生成的树,激活选中的节点,并将节点数据发送到父节点

    从后台返回的数据,还有多层子节点,需要一个生成树的组件,如果直接在页面上写循环来拼接感觉会很麻烦,因为数据的层级结构不固定. 参考网上其他人的方法,整理如下: 1. 创建一个用于循环迭代的组件,在父组 ...

  6. HTML5: HTML5 应用程序缓存

    ylbtech-HTML5: HTML5 应用程序缓存 1.返回顶部 1. HTML5 应用程序缓存 使用 HTML5,通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线 ...

  7. javsscript闭包的一种使用场景--沙箱

    ​ //沙箱:模块化,沙箱是一个隔离的环境,最大的好处就是避免全局变量的污染. var model = (function () {//一个匿名的立即执行函数 var price = 900;//这是 ...

  8. 4.Grafana展示监控数据

    Grafana是什么?我们知道Node_export监控服务器状态,但是没有具体的展示,简单来说,Grafana的主要作用就是对监控的数据进行图形化展示. docker部署 grafana我们这里采用 ...

  9. Centos6下实现Nginx+Tomcat实现负载均衡及监控

    在性能测试过程中,我们可能会关注很多指标,比如CPU.IO.网络.磁盘等,通过这些指标大致可以判断哪个环节遇到了性能瓶颈,但是当这些指标无法判断出性能瓶颈时,我们可能就需要对一些中间件进行监控,比如N ...

  10. 2019ccpc网络赛hdu6705 path

    path 题目传送门 解题思路 先用vector存图,然后将每个vector按照边的权值从小到大排序.将每个顶点作为起点的边里最短的边存入优先队列.对于存入优先队列的信息,应有边起点,终点,是其起点的 ...