【BZOJ1500】[NOI2005]维修数列
Description

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
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
10
1
10
HINT

#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define inf 1000000000
#define N 1000005
using namespace std;
queue<int> q;
int n,m,rt,sz;
int a[N],id[N],fa[N],c[N][];
int sum[N],size[N],v[N],mx[N],lx[N],rx[N];
bool tag[N],rev[N];
void updata(int x){
int l=c[x][],r=c[x][];
sum[x]=sum[l]+sum[r]+v[x];
size[x]=size[l]+size[r]+;
mx[x]=max(mx[l],mx[r]);
mx[x]=max(mx[x],rx[l]+v[x]+lx[r]);
lx[x]=max(lx[l],sum[l]+v[x]+lx[r]);//?
rx[x]=max(rx[r],sum[r]+v[x]+rx[l]);
} void pushdown(int x){
int l=c[x][],r=c[x][];
if (tag[x]){
rev[x]=tag[x]=;
if (l)tag[l]=,v[l]=v[x],sum[l]=v[x]*size[l];
if (r)tag[r]=,v[r]=v[x],sum[r]=v[x]*size[r];
if (v[x]>=){
if (l)lx[l]=rx[l]=mx[l]=sum[l];
if (r)lx[r]=rx[r]=mx[r]=sum[r];
}
else {
if (l)lx[l]=rx[l]=,mx[l]=v[l];
if (r)lx[r]=rx[r]=,mx[r]=v[r];
}
}
if (rev[x]){
rev[x]^=;rev[l]^=;rev[r]^=;
swap(lx[l],rx[l]);swap(lx[r],rx[r]);
swap(c[l][],c[l][]);swap(c[r][],c[r][]);//?
}
}
void rotate(int x,int &k){
int l,r,y=fa[x],z=fa[y];
if (c[y][]==x) l=;else l=;r=l^;
if (y==k)k=x;
else {if (c[z][]==y) c[z][]=x;else c[z][]=x;}
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
updata(y);updata(x);
} void splay(int x,int &k){
while (x!=k){
int y=fa[x],z=fa[y];
if (y!=k){
if ((c[z][]==y)^(c[y][]==x)) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
} int find(int k,int rk){
pushdown(k);
int l=c[k][],r=c[k][];
if (size[l]+==rk) return k;
if (size[l]>=rk) return find(l,rk);
return find(r,rk-size[l]-);
} int split(int k,int tot){
int x=find(rt,k),y=find(rt,k+tot+);
splay(x,rt);splay(y,c[x][]);
return c[y][];
} void build(int l,int r,int f){
if (l>r) return;
int mid=(l+r)>>,last=id[f],now=id[mid];
if (l==r){
sum[now]=a[l];size[now]=;
tag[now]=rev[now]=;
if (a[l]>=) lx[now]=rx[now]=mx[now]=a[l];
else lx[now]=rx[now]=,mx[now]=a[l];
}
else build(l,mid-,mid),build(mid+,r,mid);
v[now]=a[mid];fa[now]=last;updata(now);
c[last][mid>=f]=now;
}
void insert(int k,int tot){
for (int i=;i<=tot;i++){
if(!q.empty())id[i]=q.front(),q.pop();
else id[i]=++sz;
scanf("%d",&a[i]);
}
build(,tot,);int z=id[(+tot)>>];
int x=find(rt,k+),y=find(rt,k+);
splay(x,rt);splay(y,c[x][]);
c[y][]=z;fa[z]=y;
updata(y);updata(x);
} void rec(int x){
if (!x) return;
int l=c[x][],r=c[x][];
rec(l);rec(r);q.push(x);
fa[x]=c[x][]=c[x][]=tag[x]=rev[x]=;
} void erase(int k,int tot){
int x=split(k,tot),y=fa[x];
rec(x);c[y][]=;
updata(y);updata(fa[y]);
} void modify(int k,int tot,int val){
int x=split(k,tot),y=fa[x];
v[x]=val;tag[x]=;sum[x]=size[x]*val;
if (val>=)lx[x]=rx[x]=mx[x]=sum[x];
else lx[x]=rx[x]=,mx[x]=val;
updata(y);updata(fa[y]);
} void rever(int k,int tot){
int x=split(k,tot),y=fa[x];
if (!tag[x]){//或许会节省一点时间
rev[x]^=;
swap(c[x][],c[x][]);
swap(lx[x],rx[x]);
updata(y);updata(fa[y]);
}
} void query(int k,int tot){
int x=split(k,tot);
printf("%d\n",sum[x]);
} int main(){
scanf("%d%d",&n,&m);
mx[]=a[]=a[n+]=-inf;
for(int i=;i<=n;i++)scanf("%d",&a[i+]);
for(int i=;i<=n+;i++)id[i]=i;
build(,n+,);
rt=(n+)>>;sz=n+;
int k,tot,val;
char ch[];
while(m--)
{ //printf("%d\n",mx[rt]);
scanf("%s",ch);
if(ch[]!='M'||ch[]!='X')scanf("%d%d",&k,&tot);
if(ch[]=='I')insert(k,tot);
if(ch[]=='D')erase(k,tot);
if(ch[]=='M')
{
if(ch[]=='X')printf("%d\n",mx[rt]);
else scanf("%d",&val),modify(k,tot,val);
}
if(ch[]=='R')rever(k,tot);
if(ch[]=='G')query(k,tot);
}
return ;
}
【BZOJ1500】[NOI2005]维修数列的更多相关文章
- [BZOJ1500][NOI2005]维修数列---解题报告
Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...
- [BZOJ1500][NOI2005]维修数列 解题报告 Splay
Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...
- bzoj千题计划221:bzoj1500: [NOI2005]维修数列(fhq treap)
http://www.lydsy.com/JudgeOnline/problem.php?id=1500 1.覆盖标记用INF表示无覆盖标记,要求可能用0覆盖 2.代表空节点的0号节点和首尾的两个虚拟 ...
- [bzoj1500][NOI2005]维修数列_非旋转Treap
维修数列 bzoj-1500 NOI-2005 题目大意:给定n个数,m个操作,支持:在指定位置插入一段数:删除一个数:区间修改:区间翻转.查询:区间和:全局最大子序列. 注释:$1\le n_{ma ...
- splay模板三合一 luogu2042 [NOI2005]维护数列/bzoj1500 [NOI2005]维修数列 | poj3580 SuperMemo | luogu3391 【模板】文艺平衡树(Splay)
先是维修数列 题解看这里,但是我写的跑得很慢 #include <iostream> #include <cstdio> using namespace std; int n, ...
- BZOJ1500[NOI2005]维修数列
Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...
- BZOJ1500: [NOI2005]维修数列[splay ***]
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 12278 Solved: 3880[Submit][Statu ...
- [bzoj1500][NOI2005]维修数列——splay
题目 题解 这道题可以说是数列问题的大BOSS,也算是这一周来学习splay等数据结构的一个总结. 我们一个一个地看这些操作. 对于操作1,我们首先建一棵子树,直接接上原树即可. 对于操作2,我们找到 ...
- BZOJ1500 [NOI2005]维修数列-fhq_Treap
题面见这里 反正是道平衡树,就拿 fhq_Treap 写了写... 这道题思路基本是围绕“用 Treap 维护中序遍历” 和 中序遍历的性质 来进行的操作 所以就可以类比线段树进行一些操作 1. 建树 ...
- BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】
以前写过这道题了,但我把以前的内容删掉了,因为现在感觉没法看 重写! 题意: 维护一个数列,支持插入一段数,删除一段数,修改一段数,翻转一段数,查询区间和,区间最大子序列 splay序列操作裸题 需要 ...
随机推荐
- [改善Java代码]子列表只是原列表的一个视图
List接口提供了subList方法,其作用是返回一个列表的子列表.这与String类的subString有点类似.但是他们的功能是否相同?看代码: import java.util.ArrayLis ...
- hdu 4005 边连通度与缩点
思路:先将图进行缩点,建成一颗树,那么如果这是一条单路径树(即最大点度不超过2),就不在能删的一条边,使得不连通.因为将其头尾相连,形成一个圈,那么删任意一条边,图都是连通的. 上面的是无解的情况,如 ...
- poj 1185 炮兵阵地 状态压缩dp
思路:定义一个三维数组dp[x][i][j]其中x为now和pre两种状态,now表示当前两行最优解,pre表示出了本行外,前两行的最优解.那么状态转移方程为 dp[now][j][k]=max(dp ...
- css3 calc():css简单的数学运算-加减乘除
css3 calc():css简单的数学运算–加减乘除 多好的东西啊,不用js,一个css就解决了. .box{ border:1px solid #ddd; width:calc(100% - 10 ...
- Java Concurrency - ScheduledThreadPoolExecutor
The Executor framework provides the ThreadPoolExecutor class to execute Callable and Runnable tasks ...
- ASP.NET播客(留言时间,投票IP,留言限字数,上传视频)
留言发布时间功能: 界面: 前台代码: 在Datalist控件中: 在<%#getIsDate(Convert.ToString(Eval("issuanceDate"))) ...
- SQL语句添加,删除主键
IF EXISTS (SELECT * FROM sys.all_objects WHERE type_desc= N'主键名')begin --删除主键 alter table 表名 drop ...
- Java中几种常见排序算法
日常操作中常见的排序方法有:冒泡排序.快速排序.选择排序.插入排序.希尔排序等. 冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数 ...
- Learn Python The Hard Way学习笔记001
今天搜索了一下raw_input() 和 input()的区别,引用下原文部分内容 两个函数均能接收 字符串 ,但 raw_input() 直接读取控制台的输入(任何类型的输入它都可以接收).而对于 ...
- 一个简单的Redis结合Spring MVC架构以及实现过程
为了加快开发人员对公司项目的理解.更加容易入手和对公司项目的整体把控. 整体框架 首先介绍公司项目的整体框架,闲话少说,直接上图 整体性能分析 这就是公司的一个整体的架构,为了开发人员对架构的侧重点的 ...