思路

超级恶心的pushdown

昏天黑地的调

让我想起了我那前几个月的线段树2

错误

这恶心的一道题终于过了

太多错误,简直说不过来

pushup

pushdown

主要就是这俩不太清晰,乱pushdown

其他的写的还没啥毛病(能看出来)

代码

#include <iostream>
#include <cstdio>
#include <stack>
#include <cstring>
#include <algorithm>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn=5e5+7;
const int inf=0x3f3f3f3f;
typedef long long ll;
int read() {
int x=0,f=1;char s=getchar();
for(; s>'9'||s<'0'; s=getchar()) if(s=='-') f=-1;
for(; s>='0'&&s<='9'; s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,m,rt,cnt;
int init[maxn];
stack<int> q;//回收废弃数组
struct node
{
int ch[2],val,pri,size;
int sum,ma,lma,rma;
int lazy_fanzhuan,lazy_chenzhen;
void clear()
{
ch[1]=ch[2]=val=pri=size=sum=lazy_fanzhuan=lma=rma=0;
ma=-inf;
lazy_chenzhen=inf;
}
void iit(int x)
{
ma=sum=val=init[x];
lma=rma=max(init[x],0);
size=1;
pri=x;
}
}e[maxn];
void pushup(int a)
{
int ls=e[a].ch[0],rs=e[a].ch[1];
//sum
e[a].sum=e[ls].sum+e[rs].sum+e[a].val;
//size
e[a].size=e[ls].size+e[rs].size+1;
//ma
e[a].ma=max(max(e[ls].ma,e[rs].ma),e[ls].rma+e[a].val+e[rs].lma);
//lma
e[a].lma=max(e[ls].lma,e[ls].sum+e[a].val+e[rs].lma);
//rma
e[a].rma=max(e[rs].rma,e[rs].sum+e[a].val+e[ls].rma); }
void down_1(int a,int ad)
{
//@修改自身
e[a].lazy_chenzhen=ad;
e[a].val=e[a].lazy_chenzhen;
e[a].sum=e[a].size*e[a].val;
e[a].ma=max(e[a].sum , e[a].val);
e[a].lma=e[a].rma=max(e[a].sum , 0);
}
void down_2(int a)
{
//sum和ma是不变的
swap(e[a].lma,e[a].rma);
swap(e[a].ch[0],e[a].ch[1]);
e[a].lazy_fanzhuan^=1;
}
void pushdown(int a)
{
if(!a) return;
int ls=e[a].ch[0],rs=e[a].ch[1];
if(e[a].lazy_fanzhuan)
{
//sum和ma是不变的
if(ls) down_2(ls);
if(rs) down_2(rs);
}
if(e[a].lazy_chenzhen!=inf)
{
if(ls) down_1(ls,e[a].lazy_chenzhen);
if(rs) down_1(rs,e[a].lazy_chenzhen);
}
e[a].lazy_chenzhen=inf;
e[a].lazy_fanzhuan=0;
}
int merge(int x,int y)
{
pushdown(x),pushdown(y);
if(!x || !y) return x+y;
if(e[x].pri<e[y].pri)
{
e[x].ch[1]=merge(e[x].ch[1],y);
pushup(x);return x;
} else
{
e[y].ch[0]=merge(x,e[y].ch[0]);
pushup(y);return y;
}
}
void split(int now,int k,int &x,int &y)
{
if(!now) x=y=0,e[now].clear();
else
{
pushdown(now);
if(e[e[now].ch[0]].size+1<=k)
x=now,split(e[now].ch[1],k-e[e[now].ch[0]].size-1,e[x].ch[1],y);
else
y=now,split(e[now].ch[0],k,x,e[y].ch[0]);
pushup(now);
}
}
int GET()
{
if(!q.empty())
{
int tmp=q.top();
q.pop();
return tmp;
} else
return ++cnt;
}
int build(int l,int r)
{
if(l>r) return 0;
int mid=(l+r)>>1,p=GET();
e[p].clear();
e[p].iit(mid);
e[p].ch[0]=build(l,mid-1);
e[p].ch[1]=build(mid+1,r);
pushup(p);
return p;
}
void dfs(int now)
{
if(!now) return;
dfs(e[now].ch[0]);
q.push(now);
dfs(e[now].ch[1]);
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
n=read(),m=read();
FOR(i,1,n) init[i]=read();
rt=build(1,n);
FOR(i,1,m)
{
string s;
cin>>s;
if(s=="INSERT")
{ // 插入
int id=read(),gs=read(),x,y,z;
FOR(j,1,gs) init[j]=read();
y=build(1,gs);
split(rt,id,x,z);
rt=merge(merge(x,y),z);
} else
if(s=="DELETE")
{
int id=read()-1,gs=read(),x,y,z;
split(rt,id,x,z);
split(z,gs,y,z);
dfs(y);
rt=merge(x,z);
} else
if(s=="MAKE-SAME")
{
int id=read()-1,gs=read(),ad=read(),x,y,z;
split(rt,id,x,z);
split(z,gs,y,z);
down_1(y,ad);
rt=merge(merge(x,y),z);
} else
if(s=="REVERSE")
{
int id=read()-1,gs=read(),x,y,z;
split(rt,id,x,z);
split(z,gs,y,z);
down_2(y);
rt=merge(merge(x,y),z);
} else
if(s=="GET-SUM")
{
int id=read()-1,gs=read(),x,y,z;
split(rt,id,x,z);
split(z,gs,y,z);
cout<<e[y].sum<<"\n";
rt=merge(merge(x,y),z);
} else
if(s=="MAX-SUM")
{ //询问
cout<<e[rt].ma<<"\n";
}
}
return 0;
}

P2042 [NOI2005]维护数列的更多相关文章

  1. P2042 [NOI2005]维护数列 && Splay区间操作(四)

    到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) ...

  2. 洛谷 P2042 [NOI2005]维护数列-Splay(插入 删除 修改 翻转 求和 最大的子序列)

    因为要讲座,随便写一下,等讲完有时间好好写一篇splay的博客. 先直接上题目然后贴代码,具体讲解都写代码里了. 参考的博客等的链接都贴代码里了,有空再好好写. P2042 [NOI2005]维护数列 ...

  3. P2042 [NOI2005]维护数列[splay或非旋treap·毒瘤题]

    P2042 [NOI2005]维护数列 数列区间和,最大子列和(必须不为空),支持翻转.修改值.插入删除. 练码力的题,很毒瘤.个人因为太菜了,对splay极其生疏,犯了大量错误,在此记录,望以后一定 ...

  4. Luogu P2042 [NOI2005]维护数列(平衡树)

    P2042 [NOI2005]维护数列 题意 题目描述 请写一个程序,要求维护一个数列,支持以下\(6\)种操作:(请注意,格式栏中的下划线'_'表示实际输入文件中的空格) 输入输出格式 输入格式: ...

  5. Luogu P2042 [NOI2005]维护数列

    题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线' _ '表示实际输入文件中的空格) 输入输出格式 输入格式: 输入文件的第 1 行包含两个数 N 和 M, ...

  6. BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)

    手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.net/suncongbo/article/details/82027387 题目链接: (l ...

  7. 洛谷P2042 [NOI2005]维护数列

    #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #in ...

  8. 数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列

    339. [NOI2005] 维护数列 时间限制:3 s   内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际 ...

  9. [NOI2005] 维护数列

    [NOI2005] 维护数列 题目 传送门 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1 ...

随机推荐

  1. 事件响应模型(游戏引擎、JAVA中等应用)

    事件,我们在生活中时时在产生事件并且做出响应,如早晨出门时,看见外面下雨了,这时候我们需要带把伞等情况! 在现实生活之中事件分为人为事件和自然事件,那么在计算机操作系统中也不例外,存在两种事件 1.人 ...

  2. Python之函数&参数&参数解构

    1.1函数定义 def 函数名(参数列表): 函数体(代码块) [return 返回值] p 函数名就是标识符,命名要求一样 语句块必须缩进,约定4个空格 Python的函数没有return语句,隐式 ...

  3. python3(socket 实现udp,tcp套接字编程)

    #coding=utf-8 #客户端程序TCP 连接 import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connec ...

  4. Java集合-----Set详解

    Set是没有重复元素的集合,是无序的 1.HashSet HashSet它是线程不安全的       HashSet常用方法:   add(E element)  将指定的元素添加到此集合(如果尚未存 ...

  5. url组成

  6. Vector集合——单列集合的“祖宗”类

    是实现可增长的对象数组:所以底层也是数组: 与collection集合不同的是,vector是同步的,意味着是单线程的,意味着效率低,速度慢, 所以在jdk1.2版本之后被ArrayList集合所取代 ...

  7. LDA模型了解及相关知识

    什么是LDA? LDA是基于贝叶斯模型的,涉及到贝叶斯模型离不开“先验分布”,“数据(似然)”和"后验分布"三块.贝叶斯相关知识:先验分布 + 数据(似然)= 后验分布. 贝叶斯模 ...

  8. 2017-2018-2 20165215 实验四《Android开发基础》实验报告

    2017-2018-2 20165215 实验四<Android开发基础>实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:张家佳 学号:20165215 指导教 ...

  9. 系统调用号、errno

    最近老需要看系统调用号,errno,所以这里记一下 CentOS Linux release 7.2.1511 (Core) 3.10.0-327.el7.x86_64 [root@localhost ...

  10. flask 的session

    python的flask操作设置.获得与删除session 首先讲一下Python的flask中session与cookies的关系,session是储存在服务器中的,cookies是储存在浏览器本地 ...