NOI2005维修数列(splay)
题目描述:
Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
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
Sample Output
10
1
10
解题思路:
听说出这道题时还没有splay,所以当时是块状链表题。
6种操作:
1.插入:
常规操作,将子树建好再把前驱后继中间空出来栽上,pushup两遍愈合即可。
PS:可以用建树时的build函数适配数组
2.删除:
将整棵树像挤痘痘一样挤出来扔掉。
PS:空间开不下,需要回收废树,不要将树分解,那样浪费时间,开一个栈,将废树压入,开新点时弹出一棵树,推入左右子树,根节点格式化输出即可。
3.修改:
常规操作,只不过用bool做懒惰标记主要是我怕它区间赋0
4.翻转:
文艺平衡树模板。
PS:pushdown时若有3的bool型标记就可以清除4的标记了。
5.求和:
维护一个sum
6.最大值:
类似vijos小白逛公园维护左连续最大值,右连续最大值,中间连续最大值即可。
PS:把0号节点的中间连续最大值赋为-∞,防止ans<0
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll tr[spc].ch[0]
#define rrr tr[spc].ch[1]
#define ls ch[0]
#define rs ch[1]
const int N=;
struct trnt{
int ch[];
int fa;
bool onmi;
int lzt;
int val;
int sum;
int wgt;
int lmx,rmx,mmx;
int chd;
}tr[N];
trnt stdtr;
int n,m;
int lne[N];
int bin[N];
int top=;
int root;
int siz;
char cmd[];
int ins[N];
int org,fin;
void destory(int &spc)
{
bin[++top]=spc;
spc=;
return ;
}
int translate(void)
{
int tmp=(int)(cmd[]);
if(tmp=='S')
return ;
if(tmp=='L')
return ;
if(tmp=='K')
return ;
if(tmp=='V')
return ;
if(tmp=='T')
return ;
if(tmp=='X')
return ;
return ;
}
bool whc(int spc)
{
return tr[tr[spc].fa].rs==spc;
}
void pushup(int spc)
{
tr[spc].sum=tr[lll].sum+tr[rrr].sum+tr[spc].val;
tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+;
tr[spc].lmx=std::max(tr[lll].lmx,tr[lll].sum+tr[spc].val+tr[rrr].lmx);
tr[spc].rmx=std::max(tr[rrr].rmx,tr[rrr].sum+tr[spc].val+tr[lll].rmx);
tr[spc].mmx=std::max(tr[spc].val+tr[lll].rmx+tr[rrr].lmx,std::max(tr[lll].mmx,tr[rrr].mmx));
return ;
}
int apply()
{
if(top)
{
int spc=bin[top--];
if(lll)
bin[++top]=lll;
if(rrr)
bin[++top]=rrr;
return spc;
}
return ++siz;
}
void address(int &spc)
{
spc=apply();
tr[spc]=stdtr;
return ;
}
void new_point(int &spc,int mid,int *a,int f)
{
address(spc);
tr[spc].fa=f;
tr[spc].val=a[mid];
return ;
}
void din(int spc,int k)
{
if(!spc)
return ;
tr[spc].onmi=true;
tr[spc].lzt=k;
tr[spc].val=k;
tr[spc].sum=tr[spc].wgt*k;
tr[spc].mmx=(k>)?tr[spc].sum:k;
tr[spc].lmx=tr[spc].rmx=(k>)?tr[spc].sum:;
return ;
}
void ovt(int spc)
{
if(!spc)
return ;
tr[spc].chd^=;
std::swap(lll,rrr);
std::swap(tr[spc].lmx,tr[spc].rmx);
return ;
}
void pushdown(int spc)
{
if(tr[spc].onmi)
{
din(lll,tr[spc].lzt);
din(rrr,tr[spc].lzt);
tr[spc].lzt=;
tr[spc].chd=;
tr[spc].onmi=false;
}
if(tr[spc].chd)
{
ovt(lll);
ovt(rrr);
tr[spc].chd=;
}
return ;
}
void rotate(int spc)
{
int f=tr[spc].fa;
bool k=whc(spc);
tr[f].ch[k]=tr[spc].ch[!k];
tr[spc].ch[!k]=f;
tr[tr[f].fa].ch[whc(f)]=spc;
tr[spc].fa=tr[f].fa;
tr[f].fa=spc;
tr[tr[f].ch[k]].fa=f;
pushup(f);
pushup(spc);
return ;
}
void splay(int spc,int f)
{
while(tr[spc].fa!=f)
{
int ft=tr[spc].fa;
if(tr[ft].fa==f)
{
rotate(spc);
break;
}
if(whc(spc)^whc(ft))
rotate(spc);
else
rotate(ft);
rotate(spc);
}
if(!f)
root=spc;
return ;
}
void build(int l,int r,int &spc,int f,int *a)
{
if(l>r)
return ;
int mid=(l+r)>>;
new_point(spc,mid,a,f);
if(l==r)
{
tr[spc].lmx=tr[spc].rmx=(a[mid]>)?a[mid]:;
tr[spc].mmx=a[mid];
tr[spc].wgt=;
tr[spc].sum=a[mid];
if(l==)
org=spc;
if(l==n+)
fin=spc;
}
build(l,mid-,lll,spc,a);
build(mid+,r,rrr,spc,a);
pushup(spc);
if(l==r)
tr[spc].mmx=tr[spc].val;
return ;
}
int place(int spc,int rnk)
{
pushdown(spc);
if(tr[lll].wgt>=rnk)
return place(lll,rnk);
if(tr[lll].wgt+==rnk)
return spc;
return place(rrr,rnk-tr[lll].wgt-);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&lne[i]);
build(,n+,root,,lne);
tr[].mmx=-0x3f3f3f3f;
while(m--)
{
scanf("%s",cmd);
int opr=translate();
if(opr==)
{
int tmproot;
int pos,tot;
scanf("%d%d",&pos,&tot);
for(int i=;i<=tot;i++)
scanf("%d",&ins[i]);
build(,tot,tmproot,,ins);
splay(place(root,pos+),);
splay(place(root,pos+),root);
tr[tr[root].rs].ls=tmproot;
tr[tmproot].fa=tr[root].rs;
pushup(tr[root].rs);
pushup(root);
}else if(opr==)
{
int pos,tot;
scanf("%d%d",&pos,&tot);
splay(place(root,pos),);
splay(place(root,pos+tot+),root);
destory(tr[tr[root].rs].ls);
pushup(tr[root].rs);
pushup(root);
}else if(opr==)
{
int pos,tot,c;
scanf("%d%d%d",&pos,&tot,&c);
splay(place(root,pos),);
splay(place(root,pos+tot+),root);
pushdown(root);
pushdown(tr[root].rs);
int spc=tr[tr[root].rs].ls;
din(spc,c);
pushup(tr[root].rs);
pushup(root);
}else if(opr==)
{
int pos,tot;
scanf("%d%d",&pos,&tot);
splay(place(root,pos),);
splay(place(root,pos+tot+),root);
pushdown(root);
pushdown(tr[root].rs);
int spc=tr[tr[root].rs].ls;
ovt(spc);
pushup(tr[root].rs);
pushup(root);
}else if(opr==)
{
int pos,tot;
scanf("%d%d",&pos,&tot);
splay(place(root,pos),);
splay(place(root,pos+tot+),root);
int spc=tr[tr[root].rs].ls;
printf("%d\n",tr[spc].sum);
}else{
splay(place(root,),);
splay(place(root,tr[root].wgt),root);
printf("%d\n",tr[tr[tr[root].rs].ls].mmx);
}
}
return ;
}
-∞
NOI2005维修数列(splay)的更多相关文章
- bzoj 1500: [NOI2005]维修数列 splay
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 6556 Solved: 1963[Submit][Status ...
- BZOJ 1500: [NOI2005]维修数列 (splay tree)
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 4229 Solved: 1283[Submit][Status ...
- 【BZOJ1500】[NOI2005]维修数列 Splay
[BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行 ...
- BZOJ1500: [NOI2005]维修数列[splay ***]
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 12278 Solved: 3880[Submit][Statu ...
- [NOI2005]维修数列 Splay tree 区间反转,修改,求和,求最值
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1500 Description Input 输入文件的第1行包含两个数N和M,N表示初始时数 ...
- [bzoj1500][NOI2005]维修数列——splay
题目 题解 这道题可以说是数列问题的大BOSS,也算是这一周来学习splay等数据结构的一个总结. 我们一个一个地看这些操作. 对于操作1,我们首先建一棵子树,直接接上原树即可. 对于操作2,我们找到 ...
- BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】
以前写过这道题了,但我把以前的内容删掉了,因为现在感觉没法看 重写! 题意: 维护一个数列,支持插入一段数,删除一段数,修改一段数,翻转一段数,查询区间和,区间最大子序列 splay序列操作裸题 需要 ...
- [bzoj1500][NOI2005 维修数列] (splay区间操作)
Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目. 第2行包含N个数字,描述初始时的数列. 以下M行,每 ...
- BZOJ1500 [NOI2005]维修数列(Splay tree)
[Submit][Status][Discuss] Description 请写一个程序,要求维护一个数列,支持以下 6 种操作: 请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格 Inp ...
- bzoj1500: [NOI2005]维修数列 (Splay+变态题)
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 11353 Solved: 3553 [Submit][Status][Discuss] Descrip ...
随机推荐
- BZOJ 3544 treap (set)
我只是想找个treap的练习题-- 每回找到lower_bound 就好啦 //By SiriusRen #include <cstdio> #include <cstring> ...
- 转:Java读写文件各种方法及性能比较
干Java这么久,一直在做WEB相关的项目,一些基础类差不多都已经忘记.经常想得捡起,但总是因为一些原因,不能如愿. 其实不是没有时间,只是有些时候疲于总结,今得空,下定决心将丢掉的都给捡起来. 文件 ...
- nginx编译安装选项说明
configure 脚本确定系统所具有一些特性,特别是 nginx 用来处理连接的方法.然后,它创建 Makefile 文件. configure 支持下面的选项: –prefix= <path ...
- Python基本循环实例Day 1
输入正确的用户名和密码,显示登陆界面,超过三次输入错误则锁定,定义字符串记得加上单引号,数字可以int定义,while循环和if循环语句后加上:,break不加: print("------ ...
- Django_shell命令操作
- 最长上升子序列(LIS)nlogn模板
参考https://www.cnblogs.com/yuelian/p/8745807.html 注意最长上升子序列用lower_bound,最长不下降子序列用upper_bound 比如123458 ...
- Dcloud+mui 压缩上传图片到服务器
chooseImgFromAlbums选择图片 chooseImgFromPictures 拍照 changeToLocalUrl 转换成可用的路径 uploadpic.compressImg 压缩图 ...
- C++11 volatile 类型
volatile作用: 作为指令关键字,确保本条指令不会受到编译器的优化而省略,而且要求每次直接读值. 定义: volatile int nTest; volatile关键字是一种类型修饰符,用它声明 ...
- Activiti工作流(3):activiti核心API
ProcessEngine 说明: 1) 在Activiti中最核心的类,其他的类都是由他而来. 2) 产生方式:ProcessEngine defaultProcessEngine = Pr ...
- sparkR处理Gb级数据集
spark集群搭建及介绍:敬请关注 数据集:http://pan.baidu.com/s/1sjYN7lF 总结:使用sparkR进行数据分析建模相比R大致有3-5倍的提升 查看原始数据集:通过iri ...