339. [NOI2005] 维护数列
时间限制:3 s  
内存限制:256 MB

【问题描述】

请写一个程序,要求维护一个数列,支持以下 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

求出当前数列中和最大的一段子列,

并输出最大和

【输入格式】

输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M表示要进行的操作数目。

第 2 行包含 N 个数字,描述初始时的数列。

以下 M 行,每行一条命令,格式参见问题描述中的表格。

【输出格式】

对于输入数据中的 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

【样例说明】

初始时,我们拥有数列 2 -6 3 5 1 -5 -3 6 3

执行操作 GET-SUM 5 4,表示求出数列中从第 5 个数开始连续 4 个数字之和,1+(-5)+(-3)+6 = -1:

2     -6     3      5      1     -5    -3     6      3

执行操作 MAX-SUM,表示要求求出当前数列中最大的一段和,应为 3+5+1+(-5)+(-3)+6+3 = 10:

2     -6     3      5      1     -5    -3     6      3

执行操作 INSERT 8 3 -5 7 2,即在数列中第 8 个数字后插入-5 7 2,

2     -6     3      5      1     -5    -3     6     -5     7      2      3

执行操作 DELETE 12 1,表示删除第 12 个数字,即最后一个:

2     -6     3      5      1     -5    -3     6     -5     7      2

执行操作 MAKE-SAME 3 3 2,表示从第 3 个数开始的 3 个数字,统一修改为 2:

2	-6	3	5	1	-5	-3	6	-5	7	2

改为

2	-6	2	2	2	-5	-3	6	-5	7	2

执行操作 REVERSE 3 6,表示取出数列中从第 3 个数开始的连续 6 个数:

2           -6            2             2             2           -5            -3            6            -5            7            2

如上所示的灰色部分 2 2 2 -5 -3 6,翻转后得到 6 -3 -5 2 2 2,并放回原来位置:

2     -6     6     -3     -5     2      2      2     -5     7      2

最后执行 GET-SUM 5 4 和 MAX-SUM,不难得到答案 1 和 10。

2            -6            6            -3            -5           2             2            2             -5           7             2

【评分方法】

本题设有部分分,对于每一个测试点:

  • 如果你的程序能在输出文件正确的位置上打印 GET-SUM 操作的答案,你可以得到该测试点 60%的分数;
  • 如果你的程序能在输出文件正确的位置上打印 MAX-SUM 操作的答案,你可以得到该测试点 40%的分数;
  • 以上两条的分数可以叠加,即如果你的程序正确输出所有 GET-SUM 和MAX-SUM 操作的答案,你可以得到该测试点 100%的分数。

请注意:如果你的程序只能正确处理某一种操作,请确定在输出文件正确的位置上打印结果,即必须为另一种操作留下对应的行,否则我们不保证可以正确评分。

【数据规模和约定】

  • 你可以认为在任何时刻,数列中至少有 1 个数。
  • 输入数据一定是正确的,即指定位置的数在数列中一定存在。
  • 50%的数据中,任何时刻数列中最多含有 30 000 个数;
  • 100%的数据中,任何时刻数列中最多含有 500 000 个数。
  • 100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。
  • 100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 个,输入文件大小不超过 20MBytes。

  这道题需要注意细节,写之前请理清思路!!!

 #include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=;
const int INF=;
int fa[maxn],ch[maxn][],sz[maxn],key[maxn];
int mark[maxn],flip[maxn],sum[maxn],n,Q;
int lx[maxn],rx[maxn],mx[maxn],rt,cnt;
char s[];
void Push_up(int x){
sz[x]=sz[ch[x][]]+sz[ch[x][]]+;
sum[x]=sum[ch[x][]]+sum[ch[x][]]+key[x];
lx[x]=max(lx[ch[x][]],key[x]+sum[ch[x][]]+lx[ch[x][]]);
rx[x]=max(rx[ch[x][]],key[x]+sum[ch[x][]]+rx[ch[x][]]);
mx[x]=max(max(mx[ch[x][]],mx[ch[x][]]),key[x]+rx[ch[x][]]+lx[ch[x][]]);
} void Cover(int x,int d){
if(!x)return;
key[x]=d;mark[x]=;
sum[x]=sz[x]*d;
if(d>)lx[x]=rx[x]=mx[x]=sum[x];
else lx[x]=rx[x]=,mx[x]=d;
} void Flip(int x){
if(!x)return;
swap(ch[x][],ch[x][]);
swap(lx[x],rx[x]); //mod Kuang_bin
flip[x]^=;
} void Push_down(int x){
if(mark[x]){
Cover(ch[x][],key[x]);
Cover(ch[x][],key[x]);
mark[x]=;
}
if(flip[x]){
Flip(ch[x][]);
Flip(ch[x][]);
flip[x]=;
}
} void Rotate(int x){
int y=fa[x],g=fa[y],c=ch[y][]==x;
ch[y][c]=ch[x][c^];fa[ch[y][c]]=y;
ch[x][c^]=y;fa[y]=x;fa[x]=g;
if(g)ch[g][ch[g][]==y]=x;
Push_up(y);
} void Splay(int x,int g=){
for(int y;(y=fa[x])!=g;Rotate(x))
if(fa[y]!=g)
Rotate((ch[fa[y]][]==y)==(ch[y][]==x)?y:x);
if(!g)rt=x;
Push_up(x);
} void Rtr(int k,int g=){
int p=rt;
while(true){
Push_down(p);
if(sz[ch[p][]]+==k)break;
if(sz[ch[p][]]+<k){
k-=sz[ch[p][]]+;
p=ch[p][];
}
else
p=ch[p][];
}
Splay(p,g);
} int Insert(int x,int l,int r){
int mid=(l+r)>>,p=++cnt;
fa[p]=x;sz[p]=;
if(l<mid)ch[p][]=Insert(p,l,mid-);
scanf("%d",&key[p]);
if(r>mid)ch[p][]=Insert(p,mid+,r);
Push_up(p);
return p;
} void Init(){
cnt=;rt=;
mx[]=mx[]=-INF;
fa[]=;ch[][]=;
ch[ch[rt][]][]=Insert(ch[rt][],,n);
Push_up(ch[rt][]);
Push_up(rt);
} int main(){
freopen("seq2005.in","r",stdin);
freopen("seq2005.out","w",stdout);
scanf("%d%d",&n,&Q);
Init();mx[]=-INF;
int l,r,x,d,tot=n+;
while(Q--){
scanf("%s",s);
if(!strcmp(s,"MAX-SUM")){
Rtr();
Rtr(tot,rt);
Push_down(rt);
Push_down(ch[rt][]);
printf("%d\n",mx[ch[ch[rt][]][]]);
}
else if(!strcmp(s,"INSERT")){
scanf("%d%d",&l,&x);l+=;
Rtr(l);Rtr(l+,rt);
Push_down(rt);tot+=x;
Push_down(ch[rt][]);
ch[ch[rt][]][]=Insert(ch[rt][],,x);
Push_up(ch[rt][]);
Push_up(rt);
}
else if(!strcmp(s,"DELETE")){
scanf("%d%d",&l,&x);r=l+x+;
Rtr(l);Rtr(r,rt);tot-=x;
ch[ch[rt][]][]=;
Push_up(ch[rt][]);
Push_up(rt);
}
else if(!strcmp(s,"REVERSE")){
scanf("%d%d",&l,&x);r=l+x+;
Rtr(l);Rtr(r,rt);
Flip(ch[ch[rt][]][]);
Push_up(ch[rt][]);
Push_up(rt);
}
else if(!strcmp(s,"MAKE-SAME")){
scanf("%d%d%d",&l,&x,&d);r=l+x+;
Rtr(l);Rtr(r,rt);
Push_down(rt);
Push_down(ch[rt][]);
Cover(ch[ch[rt][]][],d);
Push_up(ch[rt][]);
Push_up(rt);
}
else if(!strcmp(s,"GET-SUM")){
scanf("%d%d",&l,&x);r=l+x+;
Rtr(l);Rtr(r,rt);
Push_down(rt);
Push_down(ch[rt][]);
printf("%d\n",sum[ch[ch[rt][]][]]);
}
}
return ;
}

数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. [NOI2005] 维护数列

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

  8. [转载]无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    转自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182631.html 1500: [NOI2005]维修数列 Time Limit: 10 Sec  Mem ...

  9. [您有新的未分配科技点] 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Description Input 输入的第1 行包含两个数N 和M(M ≤20 ...

随机推荐

  1. 11.1 afternoon

    幸运数字(number)Time Limit:1000ms Memory Limit:64MB题目描述LYK 最近运气很差,例如在 NOIP 初赛中仅仅考了 90 分,刚刚卡进复赛,于是它决定使用一些 ...

  2. Matlab使用xlsread, xlswrite函数导致excel进程无法终止的问题

    系统版本:Win7 64位 Matlab版本:R2015b 问题描述:使用excel的操作函数,比如xlsread,xlswrite,导致excel进程无法终止,任务管理器中仍残留excel进程,打开 ...

  3. C# 内存管理优化畅想(一)---- 大对象堆(LOH)的压缩

    我们都知道,.net的GC是不会压缩大对象堆的,因为其时间开销不可接受,但这是以大对象堆产生大块碎片为代价的,如果以后要分配的大对象比最大的碎片还大,那么即使它比所有碎片的总大小要小,也是无法在不扩展 ...

  4. SQL存储过程传入字段名查询.

    根据字段名和对应的值查询. (正确代码):目前发现,需要"分组,排序"等才能解决,如"order by","group by"等. SQL代 ...

  5. ContextSwitchDeadlock was detected Message(读取注册表时出现).

    google的时候,在StackOverflow中得到个暂时解决的方法: http://stackoverflow.com/questions/2797677/contextswitchdeadloc ...

  6. ORACLE多表关联UPDATE 语句

    转载至:http://blog.itpub.net/29378313/viewspace-1064069/ 为了方便起见,建立了以下简单模型,和构造了部分测试数据:在某个业务受理子系统BSS中, SQ ...

  7. wsdlLocation可以写成项目的相对路劲吗

    如果客户端的代码使用wsdl生成的话,这个地址是从wsdl描述的<service>里的<location>获取的,如果开发过程中服务地址换了,那只能手工来修改了,好像只有一个地 ...

  8. >=ios8 应用内跳转到系统设置界面-openURL

    iOS8以后,苹果允许从应用内跳转到系统设置,但是调试结果表明,跳不到具体的设置项,使用前应该判断当前是否能够跳转到系统设置. 代码: NSURL *url = [NSURL URLWithStrin ...

  9. (java)从零开始之--装饰者设计模式

    装饰者设计模式:简单定义:增强一个类的功能,而且还可以让这些装饰类互相装饰. 应用场景:当要在某个功能的基础上扩充功能,并且扩充的功能具有大量排列组合,通过继承关系会衍生出大量子类,这时候用装饰者模式 ...

  10. 原生js实现回到顶部

    网页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;网页可见区域宽: document.body.offset ...