Written with StackEdit.

Description

请写一个程序,要求维护一个数列,支持以下 \(6\) 种操作:

请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格

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 维修序列的更多相关文章

  1. [BZOJ 1500] 维护序列

    Link: BZOJ 1500 传送门 Solution: 可能平衡树维护序列的所有操作都在这了吧…… 对序列的维护$fhq treap$和$Splay$都能做 有几个注意点: 1.维护序列时始终记得 ...

  2. [BZOJ 1500]维修数列 [Splay Tree从进阶到住院]

    历尽艰辛终于A掉了这题QwQ 贴COGS评论区几句话=.= 策爷:"splay/块状链表的自虐题.".深刻理解到如果没有M倾向就不要去写这题了.. -Chenyao2333 记得b ...

  3. bzoj 1500 维修数列

    splay乱搞. 调了两个多小时...这辈子再也不想写splay了... 维护左边最大连续和右边最大连续,维护两个标记,无脑push_down.push_up就行了. 注意最大连续和至少要包含一个数. ...

  4. BZOJ 1500 维修数列【Splay】

    注意:1,内存限制,所以需要回收删除的点 2,当前节点的左连续区间和最大值=max(左子树的左连续区间和最大值,左子树的总和+当节点的值+max(右子树的左连续区间和最大值,0)):右连续区间和最大值 ...

  5. [BZOJ 1500] [NOI2005] 维修数列

    题目链接:BZOJ - 1500 题目分析 我要先说一下,这道题我写了一晚上,然后Debug了一整个白天..........再一次被自己的蒟蒻程度震惊= = 这道题是传说中的Splay维护数列的Bos ...

  6. [BZOJ 4350]括号序列再战猪猪侠 题解(区间DP)

    [BZOJ 4350]括号序列再战猪猪侠 Description 括号序列与猪猪侠又大战了起来. 众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号 序列S合法,当且仅当: 1.( )是一个 ...

  7. (WAWAWAWAWAWA) BZOJ 1858: [Scoi2010]序列操作

    二次联通门 : BZOJ 1858: [Scoi2010]序列操作 /* BZOJ 1858: [Scoi2010]序列操作 已经... 没有什么好怕的的了... 16K的代码... 调个MMP啊.. ...

  8. bzoj 1500: [NOI2005]维修数列 splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 6556  Solved: 1963[Submit][Status ...

  9. BZOJ 1500: [NOI2005]维修数列 (splay tree)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 4229  Solved: 1283[Submit][Status ...

随机推荐

  1. Django学习笔记之Django视图View

    一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. ...

  2. 平衡搜索树--红黑树 RBTree

    红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black. 通过对任何一条从根到叶子节点简单路径上的颜色来约束树的高度,红黑树保证最长路径不超过最短路径的两倍, ...

  3. [POI2001]和平委员会

    题目描述 根据宪法,Byteland民主共和国的公众和平委员会应该在国会中通过立法程序来创立. 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍. 此委员会必须满足下列条件: 每个党派都在委 ...

  4. 修改Maven源为阿里巴巴的镜像

    在C:\Users\Administrator\.m2创建setting.xml文件,内容如下 <settings xmlns="http://maven.apache.org/SET ...

  5. jq限制字符个数

    <script> $(document).ready(function () { //限制字符个数 $(".box-right .title a").each(func ...

  6. C#470多例winform 界面特效的源码

    一共470多例winform 界面特效的源码. 窗体与界面设计... 9 实例001  带历史信息的菜单    10 实例002  菜单动态合并    12 实例003  像开始菜单一样漂亮的菜单.. ...

  7. PHP 开发环境搭建

    1. PHP (1) download PHP and extra the zip file to the folder “C:\tools\php” (2) add the path “;C:\to ...

  8. Gamma函数相关matlab代码

    1.Gamma函数: Gamma函数matlab代码: x=:0.5:5syms t y=)*exp(-t),,inf) y=double(y) plot(x,y,) 图像如下: 2.lgΓ(x)函数 ...

  9. phpstrom ctrl+s无法上传的问题 解决

    首先这个不教你怎么配置同步FTP,这个教程网上太多了. 主要是配置好了上传,上传的好好的,突然某一天不能上传了,或者配置好了上传不了. 我遇到的问题是,如果你没有点击Use this server a ...

  10. LeetCode第[3]题(Java):Longest Substring Without Repeating Characters 标签:Linked List

    题目中文:没有重复字符的最长子串 题目难度:Medium 题目内容: Given a string, find the length of the longest substring without ...