bzoj 1500 维修序列
Written with StackEdit.
Description
请写一个程序,要求维护一个数列,支持以下 \(6\) 种操作:
请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格
.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
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
Sample Output
-1
10
1
10
Solution
- 大数据结构题...敲完这道题保证神清气爽...
- 我本蒟蒻的做法是用一棵非旋\(treap\)维护这个数列.
- \(split\)时按照\(size\)分割.这样分割出的区间是以下标排序的.
- \(insert\):将给的数中序遍历,建成一棵小树后,再插入整颗树中.这样个人感性理解会比较方便.初始化也可以这样做.
- \(delete\):将给的区间\(split\)出来,合并两旁的树.注意开内存栈回收空间.
- \(make-same\):将给的区间\(split\)出来,打上对应的标记.
- \(reverse\):将给的区间\(split\)出来,打上对应的标记.
- \(getsum\):将给的区间\(split\)出来,直接返回\(pushup\)时维护的对应答案.
- \(maxsum\):直接返回整颗树根节点\(pushup\)时维护的对应答案.
- 这道题的细节部分主要在\(pushup\)函数内,而因为此题中最大子段和要求选出的子段不为空(题面没说清,根据数据感性理解的),所以初始化虚拟节点\(0\)的时候也是比较讲究的.具体可以看下面的代码.
- 所以我为啥还要去学Splay呢.
#include<bits/stdc++.h>
#define inf 1e9
using namespace std;
typedef long long LoveLive;
inline int read()
{
int out=0,fh=1;
char jp=getchar();
while ((jp>'9'||jp<'0')&&jp!='-')
jp=getchar();
if (jp=='-')
{
fh=-1;
jp=getchar();
}
while (jp>='0'&&jp<='9')
{
out=out*10+jp-'0';
jp=getchar();
}
return out*fh;
}
const int MAXN=5e5+10;
struct FhqTreap
{
int x,y,z,p,q;
int idx;
int stk[MAXN],top;
int w[MAXN];
int root;
struct node{
int lson,rson,siz,key,weight;
int rev,cov;//reverse and cover
int sum,mx;//总和,最大子段和
int lm,rm;//从左/右边开始的最大子段和
}treap[MAXN];
FhqTreap()
{
idx=0;
top=0;
root=0;
top=0;
treap[0].sum=0;
treap[0].siz=0;
treap[0].mx=-inf;//特别注意.否则pushup最大子段和的时候,可能会出现空的子段.
treap[0].lm=0;
treap[0].rm=0;
treap[0].rev=0;
treap[0].cov=inf;
}
#define rt treap[o]
#define ls treap[treap[o].lson]
#define rs treap[treap[o].rson]
inline int newnode(int key)
{
int o=top?stk[top--]:++idx;
rt.lson=rt.rson=0;
rt.siz=1;
rt.key=key;
rt.weight=rand();
rt.rev=0;
rt.cov=inf;
rt.sum=key;
rt.mx=key;
rt.lm=key;
rt.rm=key;
return o;
}
void pushup(int o)
{
if(!o)
return;
rt.siz=ls.siz+rs.siz+1;
rt.sum=ls.sum+rs.sum+rt.key;
rt.lm=rt.key;
rt.lm=max(ls.lm,max(ls.sum+rt.key,ls.sum+rt.key+rs.lm));
rt.rm=rt.key;
rt.rm=max(rs.rm,max(rs.sum+rt.key,rs.sum+rt.key+ls.rm));
rt.mx=rt.key;
rt.mx=max((ls.rm>0?ls.rm:0)+rt.key+(rs.lm>0?rs.lm:0),max(ls.mx,rs.mx));//若子节点不存在,mx赋为-inf,强制选择了rt,保证不为空.
}
void upend(int o)
{
swap(rt.lson,rt.rson);
swap(rt.lm,rt.rm);
rt.rev^=1;
}
void cover(int o,int val)
{
rt.key=val;
rt.sum=rt.siz*val;
rt.mx=max(rt.sum,val);//字段长度至少为1
rt.lm=max(rt.sum,0);// remained to be updated
rt.rm=max(rt.sum,0);
rt.cov=val;
}
void pushdown(int o)
{
if(rt.rev)
{
if(rt.lson)
upend(rt.lson);
if(rt.rson)
upend(rt.rson);
}
if(rt.cov!=inf)
{
if(rt.lson)
cover(rt.lson,rt.cov);
if(rt.rson)
cover(rt.rson,rt.cov);
}
rt.rev=0;
rt.cov=inf;
}
void recover(int o)
{
if(!o)
return;
stk[++top]=o;
recover(rt.lson);
recover(rt.rson);
}
void split(int &x,int &y,int k,int o)//按子树大小分,前k个分到x中,其余y中
{
if(!o)
x=y=0;
else
{
pushdown(o);
if(k<=ls.siz)
{
y=o;
split(x,rt.lson,k,rt.lson);
}
else
{
x=o;
split(rt.rson,y,k-ls.siz-1,rt.rson);
}
pushup(o);
}
}
int merge(int x,int y)
{
if(x==0 || y==0)
return x+y;
pushdown(x);
pushdown(y);
if(treap[x].weight<treap[y].weight)
{
treap[x].rson=merge(treap[x].rson,y);
pushup(x);
return x;
}
else
{
treap[y].lson=merge(x,treap[y].lson);
pushup(y);
return y;
}
}
int BuildTree(int l,int r)//以w[l]~w[r]建树,返回树根标号
{
if(l>r)
return 0;
int mid=(l+r)>>1;
int o=newnode(w[mid]);
rt.lson=BuildTree(l,mid-1);
rt.rson=BuildTree(mid+1,r);
pushup(o);
return o;
}
int getdata(int tot)
{
for(int i=1;i<=tot;++i)
w[i]=read();
return BuildTree(1,tot);
}
void ins(int pos,int tot)
{
int o=getdata(tot);
split(x,y,pos,root);
x=merge(x,o);
root=merge(x,y);
}
void del(int pos,int tot)
{
split(x,y,pos-1,root);
split(p,q,tot,y);
root=merge(x,q);
recover(p);
}
void update(int pos,int tot,int c)
{
split(x,y,pos-1,root);
split(p,q,tot,y);
cover(p,c);
root=merge(x,merge(p,q));
}
void rev(int pos,int tot)
{
split(x,y,pos-1,root);
split(p,q,tot,y);
upend(p);
root=merge(x,merge(p,q));
}
int getsum(int pos,int tot)
{
split(x,y,pos-1,root);
split(p,q,tot,y);
int res=treap[p].sum;
root=merge(x,merge(p,q));
return res;
}
int maxsum()
{
return treap[root].mx;
}
void pr(int o)
{
if(!o)
return;
pr(rt.lson);
printf("%d ",rt.key);
pr(rt.rson);
}
void print()
{
pr(root);
puts("");
}
}T;
int n,m;
int main()
{
srand(time(NULL));
n=read(),m=read();
T.ins(0,n);
// T.print();
char op[50];
int pos,tot,c;
for(int i=1;i<=m;++i)
{
scanf("%s",op);
if(op[0]=='I')
{
pos=read();
tot=read();
T.ins(pos,tot);
}
else if(op[0]=='D')
{
pos=read();
tot=read();
T.del(pos,tot);
}
else if(op[0]=='M' && op[2]=='K')
{
pos=read();
tot=read();
c=read();
T.update(pos,tot,c);
}
else if(op[0]=='R')
{
pos=read();
tot=read();
T.rev(pos,tot);
}
else if(op[0]=='G')
{
pos=read();
tot=read();
int ans=T.getsum(pos,tot);
printf("%d\n",ans);
}
else if(op[0]=='M' && op[2]=='X')
{
int ans=T.maxsum();
printf("%d\n",ans);
}
}
return 0;
}
bzoj 1500 维修序列的更多相关文章
- [BZOJ 1500] 维护序列
Link: BZOJ 1500 传送门 Solution: 可能平衡树维护序列的所有操作都在这了吧…… 对序列的维护$fhq treap$和$Splay$都能做 有几个注意点: 1.维护序列时始终记得 ...
- [BZOJ 1500]维修数列 [Splay Tree从进阶到住院]
历尽艰辛终于A掉了这题QwQ 贴COGS评论区几句话=.= 策爷:"splay/块状链表的自虐题.".深刻理解到如果没有M倾向就不要去写这题了.. -Chenyao2333 记得b ...
- bzoj 1500 维修数列
splay乱搞. 调了两个多小时...这辈子再也不想写splay了... 维护左边最大连续和右边最大连续,维护两个标记,无脑push_down.push_up就行了. 注意最大连续和至少要包含一个数. ...
- BZOJ 1500 维修数列【Splay】
注意:1,内存限制,所以需要回收删除的点 2,当前节点的左连续区间和最大值=max(左子树的左连续区间和最大值,左子树的总和+当节点的值+max(右子树的左连续区间和最大值,0)):右连续区间和最大值 ...
- [BZOJ 1500] [NOI2005] 维修数列
题目链接:BZOJ - 1500 题目分析 我要先说一下,这道题我写了一晚上,然后Debug了一整个白天..........再一次被自己的蒟蒻程度震惊= = 这道题是传说中的Splay维护数列的Bos ...
- [BZOJ 4350]括号序列再战猪猪侠 题解(区间DP)
[BZOJ 4350]括号序列再战猪猪侠 Description 括号序列与猪猪侠又大战了起来. 众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号 序列S合法,当且仅当: 1.( )是一个 ...
- (WAWAWAWAWAWA) BZOJ 1858: [Scoi2010]序列操作
二次联通门 : BZOJ 1858: [Scoi2010]序列操作 /* BZOJ 1858: [Scoi2010]序列操作 已经... 没有什么好怕的的了... 16K的代码... 调个MMP啊.. ...
- 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 ...
随机推荐
- sql中null 和 ‘’(空字符串)
sql 中 null 和 空字符串的区别方式 在Silverlight中 数据库 需要与实体类进行映射, 假如实体类不允许为null,则 select '' as 列名 from 表名字: ...
- 20145229吴姗珊逆向BOF实践
20145229吴姗珊逆向BOF实践 实践 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. ...
- 20145109《Java程序设计》第二周学习总结
20145109 <Java程序设计>第二周学习总结 教材学习内容总结 Variable : naming rule : Camel case no default value e.g : ...
- 用adb 启动camera
adb shell am start -a android.media.action.STILL_IMAGE_CAMERA 启动camera adb shell input keyevent 27 ...
- Android -- ContentProvider 内容提供者,创建和调用
1. 概述 ContentProvider 在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentPr ...
- Flume-NG中的Channel与Transaction关系(原创)
在sink和source中(不管是内置还是自定义的),基本都有如下代码,这些代码在sink中的process方法中,而在source中自己不需要去写,在source中getChannelProcess ...
- JSP数据交互(一)
1.JSP内置对象 请求对象:request 输出对象:out 响应对象:response 应用程序对象:application 会话对象:session 页面上下文对象:pageContext 页面 ...
- Win7.还原默认打开方式
1.win7还原默认打开方式_百度知道.html(https://zhidao.baidu.com/question/1668708948433912307.html) Windows7:[47]打开 ...
- 计算机网络 - IP和端口
计算机网络分层模型 OSI分层模型:物理层.数据链路层.网络层.传输层.会话层.表示层.应用层: TCP/IP分层模型:物理+数据链路层.网络层.传输层.应用层: IP地址 IP地址是一个32位的整数 ...
- srs部署到ubuntu 18.04 server
srs.txt ubuntu 18.04 安装 srs 1. 上传srs_40.7z和h2ws.7z到linux服务器,然后远程ssh连接 (假设登陆用户名是bob,linux服务器ip是192.16 ...