题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

SOL:

我们发现这是一道fhq_treap的模板题。

我们首先要会fhq_treap。(splay也可以)

我们发现一颗树无论如何旋转(或者split后merge),其中序遍历总是不变的(这是区间操作的基础)

如果我们按照想要的中序遍历建树并且合并,我们一定能得到正确的区间,所以平衡树的区间操作是正确的。

这也是平衡树的两大建立方式之一:按中序遍历建树(另外一种是按权值建树……就是最常见的那种)

这样就涉及到一个没有出现的函数:build(建树)函数。

我们可以暴力建树:(以洛谷p3391 文艺平衡树为例)

Treap* build(int l,int r){
if (l>r) return rr;//我们有#define rr NULL
Treap *now=new Treap();//这里的值是可以改的,就是数组里的真实值
now->son[]=build(l,MID-);//递归处理
now->son[]=build(MID+,r);
now->rub();//更新该节点的信息
return now;
}

我们有2个懒标记 :flip,mark。

filp 是指指是不是被染成了同一种颜色,而mark标记是是否翻转。我们来看一下如何维护mark标记

void pushdown(Treap* x)
{ if (x && x->mark)
{ x->mark=;
swap(x->son[],x->son[]);
if (x->son[]) x->son[]->mark^=;
if (x->son[]) x->son[]->mark^=;
}
}

我们发现异常的简洁。这样我们就可以轻松的维护mark标记了。

那么我们就只剩最后一个操作了:MAX—SUM,我们便可以维护一个区间的ls,rs,maxsum三个值:

ls是从左边起的极大序列 ,rs从右边起的极大序列 。maxsum是这个区间的最大值。

那么我们合并时,新区间的最大值只有2种情况:

1.最大值是两个子区间的最大值中的一个。

2.最大值是左区间的rs并上当前节点并上右区间的ls

那么我们就做完了。

#include<bits/stdc++.h>
#define N 500007
#define MAXN 4000007
#define inf 0x3f3f3f3f
#define MARICLE __attribute__((optimize("-O2")))
using namespace std;
#define stack rrsb
int n,a[N],point;
#define sight(c) ('0'<=c&&c<='9')
#define Sight(c) ('A'<=c&&c<='Z'||c=='-')
#define abs(x) ((x)>0?(x):(-x))
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define getchar nc
inline char nc() {
static char buf[],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,,stdin),p1==p2)?EOF:*p1++;
}
MARICLE inline void read(int &x) {
static char c;
static int b;
for (b=,c=getchar(); !sight(c); c=getchar()) if (c=='-') b=-;
for (x=; sight(c); c=getchar()) x=x*+c-;
x*=b;
}
MARICLE inline void reads(char* op) {
static char c;
static int b;
for (b=,c=getchar(); !Sight(c); c=getchar());
for (; Sight(c); c=getchar()) op[b++]=c;
}
struct Treap {
Treap *ch[];
int val,key,size,sum,l,r,m;
bool flip,mark;
MARICLE Treap() {
/*val=l=r=m=-inf;sum=0;size=0;mark=flip=0;key=rand();*/
}
MARICLE void re() {
val=l=r=m=-inf;
sum=;
size=;
mark=flip=;
key=rand();
}
MARICLE inline void update() {
size=ch[]->size+ch[]->size+;
sum=val+ch[]->sum+ch[]->sum;
l=max(ch[]->l,max(ch[]->sum+val,ch[]->sum+val+ch[]->l));
r=max(ch[]->r,max(val+ch[]->sum,ch[]->r+val+ch[]->sum));
m=max(ch[]->m,max(max(,ch[]->r)+val+max(,ch[]->l),ch[]->m));
}
};
Treap *null=new Treap(),*root=null,*stack[N],*x,*last;
MARICLE inline void Maintain_flip(Treap *o) {
if(o==null)return;
o->flip^=;
swap(o->l,o->r);
}
MARICLE inline void Maintain_mark(Treap *o,int c) {
if(o==null)return;
o->val=c;
o->sum=o->size*c;
o->l=o->r=o->m=max(o->size*c,c);
o->mark=;
}
MARICLE inline void pushdown(Treap *o) {
if(o==null)return;
if(o->flip) {
o->flip^=;
Maintain_flip(o->ch[]);
Maintain_flip(o->ch[]);
swap(o->ch[],o->ch[]);
}
if(o->mark) {
Maintain_mark(o->ch[],o->val);
Maintain_mark(o->ch[],o->val);
o->mark=;
}
}
MARICLE inline Treap* newTreap(int val) {
Treap *o=new Treap();
o->ch[]=o->ch[]=null;
o->key=rand();
o->val=o->sum=val;
o->size=;
o->flip=o->mark=;
o->m=o->l=o->r=val;
return o;
}
MARICLE Treap *merge(Treap *a,Treap *b) {
if(a==null)return b;
if(b==null)return a;
pushdown(a);
pushdown(b);
if(a->key < b->key) {
a->ch[]=merge(a->ch[],b);
a->update();
return a;
} else {
b->ch[]=merge(a,b->ch[]);
b->update();
return b;
}
}
MARICLE void split(Treap *now,int k,Treap* &x,Treap* &y) {
if (now==null) {
x=y=null;
return;
}
pushdown(now);
int cmp=now->ch[]?now->ch[]->size+:;
if (k<cmp) y=now,split(y->ch[],k,x,y->ch[]);
else x=now,split(x->ch[],k-cmp,x->ch[],y);
now->update();
}
int pos,c;
MARICLE inline Treap *build() {
int p=;
for(int i=; i<=n; i++) {
read(a[i]);
x=newTreap(a[i]);
last=null;
while(p&&stack[p]->key > x->key) {
stack[p]->update();
last=stack[p];
stack[p--]=null;
}
if(p)stack[p]->ch[]=x;
x->ch[]=last;
stack[++p]=x;
}
while(p)stack[p--]->update();
return stack[];
}
MARICLE void adjust(Treap *o) {
if(o==null)return;
if(o->ch[]!=null)adjust(o->ch[]);
if(o->ch[]!=null)adjust(o->ch[]);
delete o;
}
Treap* XX,*X,*Y,*Z;
MARICLE inline void insert() {
read(pos);
read(n);
Treap *o=build();
split(root,pos,X,Y);
root=merge(merge(X,o),Y);
}
MARICLE inline void erase() {
read(pos);
read(n);
split(root,pos-,X,Y);
split(Y,n,Y,Z);
adjust(Y);
root=merge(X,Z);
}
MARICLE inline void reverse() {
read(pos);
read(n);
split(root,pos-,X,Y);
split(Y,n,Y,Z);
Maintain_flip(Y);
root=merge(merge(X,Y),Z);
}
MARICLE inline void make_same() {
read(pos);
read(n);
read(c);
split(root,pos-,X,Y);
split(Y,n,Y,Z);
Maintain_mark(Y,c);
root=merge(merge(X,Y),Z);
}
MARICLE inline int get_sum() {
read(pos);
read(n);
if(n==)return ;
split(root,pos-,X,Y);
split(Y,n,Y,Z);
int ret=Y->sum;
root=merge(merge(X,Y),Z);
return ret;
}
int m;
MARICLE void write(int x) {
if (x<) {
putchar(''+x);
return;
}
write(x/);
putchar(''+x%);
}
MARICLE inline void writeln(int x) {
if (x<) putchar('-');
write(abs(x));
putchar('\n');
}
MARICLE int main() {
null->re();
read(n);
read(m);
root=build();
char opt[];
while(m--) {
reads(opt);
// scanf("%s",opt);
switch(opt[]) {
case 'I':
insert();
break;
case 'D':
erase();
break;
case 'M':
if (opt[]!='K') writeln(root->m);
else make_same();
break;
case 'G':
writeln(get_sum());
break;
case 'R':
reverse();
break;
}
}
}

NOI 2005维护数列的更多相关文章

  1. 洛谷 2042 BZOJ 1500 NOI 2005 维护数列

    [题意概述] 维护一个数列,要求支持以下6种操作: [题解] 大Boss...可以用Treap解决 需要用到垃圾回收.线性建树. #include<cstdio> #include< ...

  2. NOI 2005 维修数列

    妈妈呀我终于过了!!!原来是数据坑我!!! 弃疗弃疗弃疗弃疗!!!!我调了一天呢....被GET_SUM 8 0打败了.... 啥也不说了....还是我太年轻.... 更新了一下常数,跑的还是可以的: ...

  3. bzoj 1500 [NOI 2005] 维修数列

    题目大意不多说了 貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧 还是有很多操作的,估计够以后当模版了.... #include <cstdio> #include < ...

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

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

  5. 【bzoj1500】 noi2005—维护数列

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 (题目链接) 题意 要求维护数列,操作有区间删除,区间插入,区间反转,区间修改,区间求和,求最 ...

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

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

  7. [NOI2005] 维护数列

    [NOI2005] 维护数列 题目 传送门 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1 ...

  8. 【NOI2005】维护数列

    https://daniu.luogu.org/problem/show?pid=2042 一道伸展树维护数列的很悲伤的题目,共要维护两个标记和两个数列信息,为了维护MAX-SUM还要维护从左端开始的 ...

  9. BZOJ1798 AHOI2009 维护数列

    1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小 ...

随机推荐

  1. Java学习之计算机基础(二)

    今天主要介绍原码.反码与补码的知识.了解原码.反码与补码的知识,可以帮助我们更好地理解在计算机内部是如何进行运算的,同时对于后面更好地学习和理解Java基本数据类型及其范围打下基础. 背景知识: 在计 ...

  2. WPF水珠效果按钮组

    效果图 相关知识 这部分基本就是废话,网上都能找到,我只不过是整理了以下.建议先不看,用到的时候可以回来看看 贝塞尔曲线 先来看两组图,有助于理解什么是贝塞尔曲线(图片取自维基百科,参考链接1) 二次 ...

  3. 出现JSONvalue failed .error is Illegal start of token

    出现JSONvalue failed .error is Illegal start of token了? 别着急,抽根烟,喝杯水.开工: 1:判断是请求前报的错还是请求后报的错!!这个很重要,我就是 ...

  4. SQL多表关联查询

        在创建关系型数据表时,根据数据库范式的要求,为了降低数据的冗余,提供数据维护的灵活性 将数据分成多个表进行存储,实际工作当中,需要多个表的信息,需要将多个表合并显示   --内连接 selec ...

  5. eclipse 鲜为人知的调试技巧,你用过多少

    今天在OSChina上看到了篇调试技巧,的确对于调试非常有帮助,而且大部分我们都没实用过,我们常常使用的调试是F5678四个键,假设你还想提高调试效率你能够尝试着用一用,写过代码做过项目的人都知道调试 ...

  6. 不用asp.net MVC,用WebForm照样能够实现MVC

    在<避开WebForm天坑,拥抱ASP.Net MVC吧>这篇博客中我讲到了ASP.net WebForm由于一些先天的"诱导犯罪"的缺陷,如今用ASP.net MVC ...

  7. Spring基础知识之依赖注入

    Spring框架的四大原则: 1)使用POJO进行轻量级和最小侵入式的开发. 2)通过依赖注入和基于接口编程实现松耦合. 3)通过AOP和默认习惯进行声明式编程. 4)使用AOP和模板(templat ...

  8. 搭建 Keepalived + Nginx + Tomcat 的高可用负载均衡架构

    1 概述 初期的互联网企业由于业务量较小,所以一般单机部署,实现单点访问即可满足业务的需求,这也是最简单的部署方式,但是随着业务的不断扩大,系统的访问量逐渐的上升,单机部署的模式已无法承载现有的业务量 ...

  9. 三.RabbitMQ之异步消息队列(Work Queue)

    上一篇文章简要介绍了RabbitMQ的基本知识点,并且写了一个简单的发送和接收消息的demo.这一篇文章继续介绍关于Work Queue(工作队列)方面的知识点,用于实现多个工作进程的分发式任务. 一 ...

  10. 《金领简历:敲开苹果、微软、谷歌的大门》【PDF】下载

    <金领简历:敲开苹果.微软.谷歌的大门>[PDF]下载链接: https://u253469.ctfile.com/fs/253469-231196331 内容简介 <金领简历:敲开 ...