输入格式

输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M 表示要进行的操作数目。 第 2 行包含 N 个数字,描述初始时的数列。 以下 M 行,每行一条命令,格式参见问题描述中的表格

输出格式

对于输入数据中的 GET-SUM 和 MAX-SUM 操作,向输出文件依次打印结 果,每个答案(数字)占一行。

你可以认为在任何时刻,数列中至少有 1 个数。

输入数据一定是正确的,即指定位置的数在数列中一定存在。

100%的数据中,任何时刻数列中最多含有 500 000 个数。

100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。

100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 。

题解

序列翻转基本操作

区间最大子段和

有了上面的铺垫,其实这些操作都可以解决了。

以下的根不做特殊说明都指区间代表子树的根。

只是有点小细节需要注意:

插入时要先把插入序列建splay,不然一个一个插入会超时。建splay时需要特判叶子节点维护一些信息,对于lmax和rmax需要将val和0取max,因为在父亲节点更新lmax是可能为左区间+父亲节点本身,如果右区间lmax直接取val,就可能取不到这种情况,或许比较三种情况可以解决这个问题,但是很麻烦不是吗。

删除的时候,把这段区间提取出来删除即可。不过因为空间原因需要回收节点编号,所以需要遍历这棵子树回收,用队列装编号。最多插入4e6个数,所以最多遍历4e6个点。

区间覆盖的时候,提取区间后,在根打上覆盖标记,维护节点信息:注意如果val是负数最大子段和赋成val。

翻转提取区间,在根打上翻转标记,将lmax和rmax交换。

求和提取区间输出根的sum即可。

这道题的最大子段和是整个序列的,其实降低了一点难度,直接输出整颗splay的根的最大子段和即可。

下传在find里面。

建初始序列时要在收尾插入两个最小值,因为最大值在求最大子段和会有影响。

还有对于0号节点的最大子段和赋最小值,因为一些没有儿子的点更新信息会用到。

#include<bits/stdc++.h>
using namespace std;#define ll long long
const ll oo=1000000;
const int maxn=500005;
int n,m;
ll a[maxn],num,id[maxn],root;
queue<int> q;
struct Splay{int s[2],fa,size,tag,cover;//tag:当前节点是否需要交换儿子
  ll val,sum,dat,lmax,rmax;
}tr[maxn];template<class T>inline void read(T &x){x=0;int f=0;char ch=getchar();while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}x= f ? -x : x ;
}ll max(ll x,ll y){return x>y ? x : y ;}void update(Splay &ret,Splay lx,Splay ry){ret.size=lx.size+ry.size+1;ret.sum=lx.sum+ry.sum+ret.val;ret.lmax=max(lx.lmax,lx.sum+ret.val+ry.lmax);ret.rmax=max(ry.rmax,ry.sum+ret.val+lx.rmax);ret.dat=max(max(lx.dat,ry.dat),lx.rmax+ret.val+ry.lmax);//给0赋值防止了出事//printf("-%d-",ret.val);
}void update(int x){update(tr[x],tr[tr[x].s[0]],tr[tr[x].s[1]]);
}int build(int l,int r,int f){//printf("%d %d\n",l,r);if(l>r) return 0;int mid=(l+r)>>1,now=id[mid];tr[now].fa=f;tr[now].val=a[mid];tr[now].cover=oo;if(l==r){tr[now].size=1;tr[now].sum=tr[now].val;tr[now].lmax=tr[now].rmax=max(0,tr[now].val);tr[now].dat=tr[now].val;//记得赋值return now;}tr[now].s[0]=build(l,mid-1,now);tr[now].s[1]=build(mid+1,r,now);update(now);return now;
}void put_cover(int x,ll val){if(!x) return ;tr[x].val=tr[x].cover=val;tr[x].sum=val*tr[x].size;tr[x].lmax=tr[x].rmax= val>=0 ? tr[x].sum : 0;tr[x].dat= val>=0 ? tr[x].sum : val;//必须选取至少一个元素
}void put_tag(int x){if(!x) return ;tr[x].tag^=1;swap(tr[x].s[0],tr[x].s[1]);swap(tr[x].lmax,tr[x].rmax);
}void push_down(int x){if(tr[x].cover!=oo){put_cover(tr[x].s[0],tr[x].cover);put_cover(tr[x].s[1],tr[x].cover);tr[x].cover=oo;}if(tr[x].tag){put_tag(tr[x].s[0]);put_tag(tr[x].s[1]);tr[x].tag=0;}
}void debug(int x){push_down(x);if(tr[x].s[0]) debug(tr[x].s[0]);printf("%lld ",tr[x].val);if(tr[x].s[1]) debug(tr[x].s[1]);
}int find(int k){int now=root;while(1){//printf("%d %d\n",k,now);
    push_down(now);if(tr[tr[now].s[0]].size>=k) {now=tr[now].s[0];continue;}k-=tr[tr[now].s[0]].size;if(k==1) return now;k--;now=tr[now].s[1];}
}int get(int x){return tr[tr[x].fa].s[1]==x;
}void connect(int x,int y,int d){tr[y].s[d]=x;tr[x].fa=y;
}void rotate(int x){int f=tr[x].fa,ff=tr[f].fa;int d1=get(x),d2=get(f);int cs=tr[x].s[d1^1];connect(x,ff,d2);connect(f,x,d1^1);connect(cs,f,d1);update(f);update(x);
}void splay(int x,int go){if(go==root) root=x;go=tr[go].fa;while(tr[x].fa!=go){int f=tr[x].fa;if(tr[f].fa==go) rotate(x);else if(get(x)==get(f)) {rotate(f);rotate(x);}else {rotate(x);rotate(x);}}
}void insert(){int pos,tot;read(pos);read(tot);n+=tot;for(int i=1;i<=tot;i++){read(a[i]);if(!q.empty()) id[i]=q.front(),q.pop();else id[i]=++num;}int nowroot=build(1,tot,0);int x=find(pos+1),y=find(pos+2);splay(x,root);splay(y,tr[x].s[1]);tr[nowroot].fa=y;tr[y].s[0]=nowroot;update(y);update(x);
}void clean(int x){tr[x]=(Splay){{0,0},0,0,0,oo,0,0,0,0,0};
}void recycle(int x){if(tr[x].s[0]) recycle(tr[x].s[0]);if(tr[x].s[1]) recycle(tr[x].s[1]);clean(x);q.push(x);
}void dele(){int pos,tot;read(pos);read(tot);n-=tot;int x=find(pos),y=find(pos+tot+1);splay(x,root);splay(y,tr[x].s[1]);recycle(tr[y].s[0]);tr[y].s[0]=0;update(y);update(x);
}void modify(){int pos,tot;ll val;read(pos);read(tot);read(val);int x=find(pos),y=find(pos+tot+1);splay(x,root);splay(y,tr[x].s[1]);put_cover(tr[y].s[0],val);update(y);update(x);
}void reverse(){int pos,tot;read(pos);read(tot);int x=find(pos),y=find(pos+tot+1);splay(x,root);splay(y,tr[x].s[1]);put_tag(tr[y].s[0]);update(y);update(x);
}ll querysum(){int pos,tot;read(pos);read(tot);int x=find(pos),y=find(pos+tot+1);splay(x,root);splay(y,tr[x].s[1]);//printf("%d %d\n",x,y);//printf("%d\n",tr[tr[y].s[0]].size);//putchar(10);//debug(tr[y].s[0]);//putchar(10);return tr[tr[y].s[0]].sum;
}ll querydat(){int x=find(1),y=find(n);splay(x,root);splay(y,tr[x].s[1]);return tr[tr[y].s[0]].dat;
}int main(){read(n);read(m);tr[0].dat=a[1]=a[n+2]=-oo;//给零赋值,不然建树会出锅for(int i=1;i<=n;i++) read(a[i+1]);for(int i=1;i<=n+2;i++) id[i]=++num;n=n+2;root=build(1,n,0);for(int i=1;i<=m;i++){char opt[15];scanf("%s",opt);if(opt[2]=='S') insert();else if(opt[2]=='L') dele();else if(opt[2]=='K') modify();else if(opt[2]=='V') reverse();else if(opt[2]=='T') printf("%lld\n",querysum());else printf("%lld\n",tr[root].dat);//putchar(10);//debug(root);//putchar(10);
  }
}

View Code

转载于:https://www.cnblogs.com/sto324/p/11297521.html

[NOI2005]维护数列相关推荐

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

    BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay) 手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.ne ...

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

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

  3. [luogu2042] [NOI2005]维护数列

    前言 写写比较麻烦的这题 题目相关 题目大意 写一个大数据结构 数据范围 20000 题目链接 前置 先过模板题,比如会个非旋treap,写一下,通过[luogu3369][模板]普通平衡树 poss ...

  4. [NOI2005]维护数列 恶心到毁天灭地的splay

    传送门 debug到死2333. 虽然说是splay维护序列模板,作为蒟蒻的我还是GG %%%考场A的dalao Orz  Orz. 其实不开long long也行,inf开成0x3f3f3f3f也可 ...

  5. [BZOJ1500][NOI2005]维修数列(splay)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 16266  Solved: 5410 [Submit][Sta ...

  6. 数据结构之fhq-treap——Chef and Sets,[HNOI2012]永无乡,Play with Chain,[NOI2005]维修数列(结构体版代码)

    因为非常板,所以主要是代码 Tyvj 1728 普通平衡树 Chef and Sets [HNOI2012]永无乡 Play with Chain [NOI2005]维修数列 题目很水,所以可能会出现 ...

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

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

  8. 【BZOJ1500】[NOI2005]维修数列 Splay

    [BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目. 第2 ...

  9. JZOJ 2413. 【NOI2005】维护数列

    Description 请写一个程序,要求维护一个数列,支持以下6种操作:(请注意,格式栏中的下划线' _ '表示实际输入文件中的空格) 1. 插入 INSERT_posi_tot_c1_c2_-_c ...

最新文章

  1. 【笔记】与Android酱的第一周
  2. onrsd.exe应用程序错误
  3. linux+C环境下动态管理头文件和库文件
  4. 计算机组成原理认识fpga,计算机组成原理课程设计-基于EDA和FPGA技术的8位模型计算机的设计与实现_精品.doc...
  5. crosstool-ng 编译交叉工具链的常见错误及解决办法
  6. Bootstrap之栅格系统
  7. 06002_Redis概述
  8. sql子句的执行顺序_SQL Server查询执行计划– WHERE子句的示例
  9. android 标题栏进度圈使用方法,Android 标题栏显示进度条
  10. 《嵌入式 – GD32开发实战指南》第10章 串口通信
  11. 手机访问电脑虚拟服务器,User Agent Switcher插件使用教程【电脑模拟手机访问网站】...
  12. MySQL frm、MYD、MYI数据文件恢复
  13. TextView 的 StaticLayout,比你想象中复杂点!
  14. 推荐一款特别厉害的在线工具,程序员的百宝箱
  15. 两款非常好的Redis 可视化管理工具:Another Redis Desktop Manager、QuickRedis
  16. Star Trek强势来袭 开启元宇宙虚拟与现实的梦幻联动
  17. Axure 蚂蚁设计团队组件库 让交互稿美美搭
  18. linux 命令查询主机名,linux如何查看主机名?
  19. ASTM D 4804非刚性固体塑料可燃性试验
  20. 有没有测试游戏天赋的软件,测测你的电竞天赋-测测你的电竞天赋有多高小游戏v1.0...

热门文章

  1. 微信公众平台消息接口星标功能
  2. 《OpenCV3编程入门》学习笔记7 图像变换(五 )直方图均衡化
  3. C语言程序设计 细节总结(链表)
  4. http和dubbo的区别_(转载)Dubbo 接口是什么? 与http 接口有什么区别
  5. Bqq服务器的缓存文件放什么目录,如何使文件系统缓存失效? - How to invalidate the file system cache? - 开发者知识库...
  6. html站点相对路径,HTML的相对路径和绝对路径?
  7. 前端 重构时需要注意的事项_驾驶式扫地车的功能特点和使用时需要注意事项...
  8. 华为服务器内存条在主板位置,服务器主板内存
  9. android 本地图片uri格式不一致,Android本地相册图片URI转换绝对路径
  10. linux服务器六个状态,六、Linux_SSH服务器状态