数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列
内存限制: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] 维护数列的更多相关文章
- splay模板三合一 luogu2042 [NOI2005]维护数列/bzoj1500 [NOI2005]维修数列 | poj3580 SuperMemo | luogu3391 【模板】文艺平衡树(Splay)
先是维修数列 题解看这里,但是我写的跑得很慢 #include <iostream> #include <cstdio> using namespace std; int n, ...
- 洛谷 P2042 [NOI2005]维护数列-Splay(插入 删除 修改 翻转 求和 最大的子序列)
因为要讲座,随便写一下,等讲完有时间好好写一篇splay的博客. 先直接上题目然后贴代码,具体讲解都写代码里了. 参考的博客等的链接都贴代码里了,有空再好好写. P2042 [NOI2005]维护数列 ...
- P2042 [NOI2005]维护数列[splay或非旋treap·毒瘤题]
P2042 [NOI2005]维护数列 数列区间和,最大子列和(必须不为空),支持翻转.修改值.插入删除. 练码力的题,很毒瘤.个人因为太菜了,对splay极其生疏,犯了大量错误,在此记录,望以后一定 ...
- P2042 [NOI2005]维护数列 && Splay区间操作(四)
到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) ...
- Luogu P2042 [NOI2005]维护数列(平衡树)
P2042 [NOI2005]维护数列 题意 题目描述 请写一个程序,要求维护一个数列,支持以下\(6\)种操作:(请注意,格式栏中的下划线'_'表示实际输入文件中的空格) 输入输出格式 输入格式: ...
- [NOI2005]维护数列(区间splay)
[NOI2005]维护数列(luogu) 打这玩意儿真是要了我的老命 Description 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文 ...
- [NOI2005] 维护数列
[NOI2005] 维护数列 题目 传送门 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1 ...
- [转载]无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )
转自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182631.html 1500: [NOI2005]维修数列 Time Limit: 10 Sec Mem ...
- [您有新的未分配科技点] 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MB Description Input 输入的第1 行包含两个数N 和M(M ≤20 ...
随机推荐
- 【python之路8】python基本数据类型(二)
基本数据类型 4.列表(list) 创建列表 name_list = ['zhao','qian','sun','li'] 基本操作 索引 print(name_list[0]) #返回zhao pr ...
- <legend>标签
健康信息身高: 体重: 如果表单周围没有边框,说明您的浏览器太老了. <!DOCTYPE HTML> <html> <body> <form> < ...
- java判断字符串是否为空的方法总结
http://blog.csdn.net/qq799499343/article/details/8492672 以下是java 判断字符串是否为空的四种方法: 方法一: 最多人使用的一个方法, 直观 ...
- ios 动画效果CATransition笔记
初学ios开发,很多概念还不清楚,所以只有边学边做例子.又怕学了后面忘了前面,因此用自己的博客来纪录自己的学习历程,也是对自己学习不要懈怠做个监督. 刚学ios做动画效果.因为ios封装得很好,实现i ...
- 用layer添加UIView的动画
项目有时会遇到用UIView 添加动画的情况,这里我觉得在layer上添加动画比较好,因为可以详细地设定动画属性,方便理解 下面是一个旋转动画: -(void)roundBtnAction:(id)s ...
- 关于ASIHTTPRequest连续请求,并发连续,间隔时间很小崩溃问题
在不停的刷新ASIHttpRequest的网络请求时,总是在刷新几次之后,整个app崩溃掉.我的app使用的ARC模式,以为可以自动释放到request的请求.经过摸索,还是需要在dealloc函数加 ...
- PictureBox内的图片拖动功能
当 PictureBox内的图片太大,超过PictureBox边框时可以用下面的方法来实现, 通过重绘来实现 : Code bool wselected = false; Point p = ...
- Spring+AOP+Log4j 用注解的方式记录指定某个方法的日志
一.spring aop execution表达式说明 在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut"切入点" 例如定义 ...
- 【vc】6_菜 单
1.菜单命令响应函数: 提示:MFC都是采用大写字母来标识资源ID号的:为了区分资源类型,一般遵循这样一个原则:在“ID”字符串后加上一个标识资源类型的字母.例:菜单资源(Menu):ID_Mxxx: ...
- C# 程序性能提升篇-2、类型(字段类型、class和struct)的错误定义所影响性能浅析
前景提要: 编写程序时,也许你不经意间,就不知不觉的定义了错误的类型,从而发生了额外的性能消耗,从而降低了效率,不要说就发生那么一次两次,如果说是程序中发生了循环.网络程序(不断请求处理的)等这些时候 ...