NOI2005维修数列(splay)
题目描述:
Description
.png)
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 ...
随机推荐
- HDU 5389 Zero Escape(DP + 滚动数组)
Zero Escape Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) To ...
- poj1062 Bellman 最短路应用
昂贵的聘礼 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 41066 Accepted: 11959 Descripti ...
- .net core的安装
安装完成后的路径在C:\Program Files\dotnet https://github.com/dotnet/cli/issues/390 ===2017年06月29日=== 安装成功之后,配 ...
- HDU 4372 Count the Buildings
Count the Buildings Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- P2038 无线网络发射器选址
题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻 ...
- 参考分享《Python深度学习》高清中文版pdf+高清英文版pdf+源代码
学习深度学习时,我想<Python深度学习>应该是大多数机器学习爱好者必读的书.书最大的优点是框架性,能提供一个"整体视角",在脑中建立一个完整的地图,知道哪些常用哪些 ...
- cogs 1456. [UVa 10881,Piotr's Ants]蚂蚁
1456. [UVa 10881,Piotr's Ants]蚂蚁 ★ 输入文件:Ants.in 输出文件:Ants.out 简单对比时间限制:1 s 内存限制:128 MB [题目描述 ...
- 游戏开发之UDK引擎介绍和模型导入
2014-09-18 10:01:3 3.7.5" style="border:0px; vertical-align:middle; max-width:100%"&g ...
- vim 基础学习之普通模式
.操作 = 操作符 + 动作 aaa bbb例如,d是删除命令,b是移动到距离光标最近的字符串开头当我们执行db的时候,就会删除光标(不包括光标位置)到最近字串开头之间的字符dj则会删除光标所在行以及 ...
- Ajax缓存原理
一.什么是Ajax缓存原理? Ajax在发送的数据成功后,会把请求的URL和返回的响应结果保存在缓存内,当下一次调用Ajax发送相同的请求时,它会直接从缓存中把数据取出来,这是为了提高页面的响应速度和 ...