洛谷 2042 BZOJ 1500 NOI 2005 维护数列
【题意概述】
维护一个数列,要求支持以下6种操作:

【题解】
大Boss。。。可以用Treap解决
需要用到垃圾回收、线性建树。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls (a[u].l)
#define rs (a[u].r)
using namespace std;
const int maxn=;
int n,m,k,x,y,z,top,root,recs[maxn],bs[maxn];//recs-->recycle_stack, bs-->build_stack
char c,c2;
struct treap{int l,r,size,rnd,v,sum,max,lsum,rsum,num; bool same,rev;}a[maxn];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
inline int max(int x,int y){return x>y?x:y;}
inline int newnode(int v){a[recs[top--]]=(treap){,,,rand(),v,v,v,v,v,,,}; return recs[top+];}//新建节点
void recycle(int u){if(u) recs[++top]=u,recycle(ls),recycle(rs);}//垃圾回收
inline void reverse(int u){//区间翻转
swap(ls,rs); swap(a[u].lsum,a[u].rsum);
a[ls].rev^=; a[rs].rev^=;
}
inline void set_same(int u,int v){//区间设为同个数
a[u].same=; a[u].v=a[u].num=v; a[u].sum=v*a[u].size;
a[u].max=a[u].lsum=a[u].rsum=(v>=?a[u].sum:v);
}
void down(int u){//下传标记
if(a[u].rev){
if(ls) reverse(ls);
if(rs) reverse(rs);
a[u].rev^=;
}
if(a[u].same){
if(ls) set_same(ls,a[u].num);
if(rs) set_same(rs,a[u].num);
a[u].same=a[u].num=;
}
}
void up(int u){//上传标记
a[u].size=a[ls].size+a[rs].size+;
a[u].sum=a[ls].sum+a[rs].sum+a[u].v;
a[u].max=max(max(a[ls].max,a[rs].max),max(a[ls].rsum,)+a[u].v+max(a[rs].lsum,));
a[u].lsum=max(a[ls].lsum,a[ls].sum+a[u].v+max(a[rs].lsum,));
a[u].rsum=max(a[rs].rsum,a[rs].sum+a[u].v+max(a[ls].rsum,));
}
void split(int u,int k,int &x,int &y){//分裂
down(u);
if(!k){x=; y=u; return;}
if(a[u].size==k){x=u; y=; return;}
if(a[ls].size>=k) split(ls,k,x,ls),y=u;
else split(rs,k-a[ls].size-,rs,y),x=u;
up(u);
}
int merge(int x,int y){//合并
if(!x||!y) return x+y;
if(a[x].rnd<a[y].rnd){down(x); a[x].r=merge(a[x].r,y); up(x); return x;}
else{down(y); a[y].l=merge(x,a[y].l); up(y); return y;}
}
void build(int &root,int n){//线性建树
int bstop=; bs[++bstop]=newnode(read());
for(int i=;i<n;i++){
int now=newnode(read());
while(top&&a[now].rnd<a[bs[bstop]].rnd) up(bs[bstop]),a[now].l=bs[bstop--];
if(bstop) a[bs[bstop]].r=now;
bs[++bstop]=now;
}
while(bstop) up(bs[bstop--]);
root=bs[];
}
void out(int u){
if(ls) out(ls);
printf("%d ",a[u].v);
if(rs) out(rs);
}
void Insert(){//插入
int x,y,insroot=;
split(root,read(),x,y);
build(insroot,read());
root=merge(x,merge(insroot,y));
//out(root);
}
void Delete(){recycle(y); y=;}//删除
void Prepare(){
srand();
for(int i=maxn;i;i--) recs[++top]=i;
a[].max=a[].lsum=a[].rsum=-2e9;
}
int main(){
Prepare();
n=read(); m=read(); build(root,n); //out(root);
//for(int i=1;i<=n;i++) root=merge(root,newnode(read()));
while(m--){
c=getchar(); while(c!='I'&&c!='D'&&c!='K'&&c!='R'&&c!='G'&&c!='X') c=getchar();
c2=getchar(); while(c2!='-'&&c2!=' ') c2=getchar();
if(c=='X'){//max_sum
printf("%d\n",a[root].same?(a[root].num?a[root].num*a[root].size:a[root].num):a[root].max);
continue;
}
if(c=='I'){Insert(); continue;}//insert
split(root,read()-,x,y);
split(y,read(),y,z);
if(c=='D') Delete();//delete
if(c=='K') set_same(y,read());//set_same
if(c=='R') a[y].rev^=,reverse(y);//reverse
if(c=='G') printf("%d\n",a[y].same?a[y].num*a[y].size:a[y].sum);//get_sum
root=merge(merge(x,y),z);
}
return ;
}
洛谷 2042 BZOJ 1500 NOI 2005 维护数列的更多相关文章
- bzoj 1500 [NOI 2005] 维修数列
题目大意不多说了 貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧 还是有很多操作的,估计够以后当模版了.... #include <cstdio> #include < ...
- NOI 2005维护数列
题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 输入输出格式 输入格式: 输入文件的第 1 行包含两个数 N 和 M, ...
- 洛谷 P1486 BZOJ 1503 NOI 2004 郁闷的出纳员 fhq treap
思路: 1. 此处的fhq treap的分裂是按照权值分裂然后插入的.将小于k的分为一棵子树,大于等于k的分为另一棵子树. 2. 删除的时候只要将大于等于min的分裂到以root为根的树中,另一部分不 ...
- BZOJ 1500 洛谷2042维护序列题解
BZ链接 洛谷链接 这道题真是丧心病狂.... 应该很容易就可以看出做法,但是写代码写的....... 思路很简单,用一个平衡树维护一下所有的操作就好了,重点讲解一下代码的细节 首先如果按照常规写法的 ...
- 洛谷.2042.[NOI2005]维护数列(Splay)
题目链接 2017.12.24 第一次写: 时间: 2316ms (1268ms) 空间: 19.42MB (19.5MB)(O2) 注:洛谷测的时间浮动比较大 /* 插入一段数:将这些数先单独建一棵 ...
- 洛谷 P2023 BZOJ 1798 [AHOI2009]维护序列
题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一 ...
- 洛谷 P2587 BZOJ 1034 [ZJOI2008]泡泡堂
题目描述 //不知道为什么BZOJ和洛谷都没有这幅图了,大牛们几年前的博客上都有这幅图的,把它贴上来吧 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省 ...
- 洛谷 P3187 BZOJ 1185 [HNOI2007]最小矩形覆盖 (旋转卡壳)
题目链接: 洛谷 P3187 [HNOI2007]最小矩形覆盖 BZOJ 1185: [HNOI2007]最小矩形覆盖 Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, ...
- 洛谷 P4175: bzoj 1146: [CTSC2008]网络管理
令人抓狂的整体二分题.根本原因还是我太菜了. 在学校写了一个下午写得头晕,回家里重写了一遍,一个小时就写完了--不过还是太慢. 题目传送门:洛谷P4175. 题意简述: 一棵 \(n\) 个结点的树, ...
随机推荐
- 将分布式-队列的实现交给redis
import requestsimport reimport timefrom redis import Redisimport threading REDIS_HOST, REDIS_PORT, P ...
- sqlserver 触发器实例代码
定义: 何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序.触发器是一个特殊的存储过程. 常见的触发器有三种:分别应用于Insert , Update ...
- bzoj 1601 灌水
题目大意: 决定把水灌到n块农田,农田被数字1到n标记 把一块土地进行灌水有两种方法,从其他农田饮水,或者这块土地建造水库 建造一个水库需要花费wi,连接两块土地需要花费Pij. 计算所需的最少代价 ...
- MSP430 G2553 Timer 中断总结
目前总共用到了四个中断向量,我觉得已经把G2553的所有定时器中断都用到了. 定时器有两个,TA0与TA1,每个定时器又有两个中断向量 1,CCR0到达时的中断,在计数模式时候很有用,平时定时器的基本 ...
- eclipse的快捷键---调试
1:查看类或接口的方法 Ctrl+T 2:debug调试查看信息 Ctrl+Shift+i 3:debug调试快捷键 (1):F11好像是重新运行debug. (2):F8直接输出结果.(3):F5单 ...
- 如何判断js的变量的数据类型
文章首发: http://www.cnblogs.com/sprying/p/4349426.html 本文罗列了一般的Js中类型检测的方法,实际上是每个新手在构建Js知识体系时,都要知晓的,而我只是 ...
- [Swift通天遁地]五、高级扩展-(10)整形、浮点、数组、字典、字符串、点、颜色、图像类的实用扩展
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- Mac上随时切换PYTHON版本
在MAC上,默认安装了python2.*,自己又安装了python3.*:假如我们需要在终端上随时切换python控制台到需要的版本,可以采用下面的方法. 1.用命令 sudo vi ~/.bas ...
- Squirrel的安装(windows上Phoneix可视化工具)
一.下载安装 下载地址:http://www.squirrelsql.org/下载所需版本 或者 从网址http://www.squirrelsql.org/下载相应版本的squirrel ...
- 查看当前linux版本
lsb_release -a 如果命令不存在,则yum安装 yum install redhat-lsb