BZOJ 1500: [NOI2005]维修数列 splay
2017-11-29 09:06
591 查看
1500: [NOI2005]维修数列
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 15162 Solved: 5009
[Submit][Status][Discuss]
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
9 82 -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
-110
1
10
HINT
真是一道splay练手好题
恶心死我了
由于做之前就知道 肯定很恶心 所以就先读了hzwer的代码
最后还是调了好久好久。。。。
数组含义如下
V 权值 sum 权值和 mx 最大连续和 mxl 从左开始最大连续和 mxr从右开始最大连续和
rev 是否翻转 tag 是否有权值覆盖
讲一下我觉得需要注意的地方
1. mxl mxr 可以为0
因为平衡树上的区间 mid 不包括在左右儿子中
2. 注意0号节点的V和mx
如果你也像BJ一样直接pushup 那么没有左右儿子就很有可能被0 pushup
3.注意更新时判是否有左右儿子
同上
4. rever最好不要像通常的只打标记 到了再转
应该像线段树一样 直接转 标记表示儿子是否要再打标记 因为还有一个赋值tag
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=500100,inf=0X3f3f3f3f;
int root;
int ch
[2],size
,fa
;
int V
,sum
,mx
,mxl
,mxr
;
bool rev
,tag
;
int st
,top,sz;
inline int newnode()
{return top ? st[top--] : ++sz;}
inline void pushup(int k)
{
int ls=ch[k][0],rs=ch[k][1];
size[k]=size[ls]+size[rs]+1;
sum[k]=V[k]+sum[ls]+sum[rs];
mx[k]=max(mx[ls],mx[rs]);
mx[k]=max(mx[k],mxl[rs]+mxr[ls]+V[k]);
mxl[k]=max(mxl[ls],sum[ls]+V[k]+mxl[rs]);
mxr[k]=max(mxr[rs],sum[rs]+V[k]+mxr[ls]);
}
inline void pushdown(int k)
{
int ls=ch[k][0],rs=ch[k][1];
if(tag[k])
{
rev[k]=tag[k]=0;
int val=V[k];
if(ls)tag[ls]=1,V[ls]=val,sum[ls]=val*size[ls];
if(rs)tag[rs]=1,V[rs]=val,sum[rs]=val*size[rs];
if(val>=0)
{
if(ls)mxl[ls]=mxr[ls]=mx[ls]=sum[ls];
if(rs)mxl[rs]=mxr[rs]=mx[rs]=sum[rs];
}
else
{
if(ls)mxl[ls]=mxr[ls]=0,mx[ls]=val;
if(rs)mxl[rs]=mxr[rs]=0,mx[rs]=val;
}
}
if(rev[k])
{
rev[k]=0;
rev[ls]^=1;rev[rs]^=1;
swap(ch[ls][0],ch[ls][1]);
swap(mxl[ls],mxr[ls]);
swap(ch[rs][0],ch[rs][1]);
swap(mxl[rs],mxr[rs]);
}
}
int pos
;
void build(int l,int r,int pre)
{
if(l>r)return ;
int mid=(l+r)>>1;
fa[pos[mid]]=pos[pre];
ch[pos[pre]][mid>pre]=pos[mid];
build(l,mid-1,mid);
build(mid+1,r,mid);
pushup(pos[mid]);
}
int find(int k,int rk)
{
pushdown(k);
if(size[ch[k][0]]>=rk)
return find(ch[k][0],rk);
if(size[ch[k][0]]+1<rk)
return find(ch[k][1],rk-1-size[ch[k][0]]);
return k;
}
inline void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
l=(x==ch[y][1]);r=l^1;
if(y==k) k=x;
else ch[z][ch[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x,int &k)
{
int y,z;
while(x!=k)
{
y=fa[x];z=fa[y];
if(y!=k)
{
if((ch[y][0]==x)^(ch[z][0]==y)) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int split(int x,int y)
{
x=find(root,x);y=find(root,y+2);
splay(x,root);splay(y,ch[root][1]);
return ch[y][0];
}
void recycle(int k)
{
if(!k)return ;
recycle(ch[k][0]);recycle(ch[k][1]);
fa[k]=ch[k][0]=ch[k][1]=0;
mx[k]=mxl[k]=mxr[k]=0;
tag[k]=rev[k]=0;
V[k]=sum[k]=0;
size[k]=0;
st[++top]=k;
}
void insert(int k,int num)
{
for(int i=1;i<=num;++i)
{
pos[i]=newnode();
V[pos[i]]=read();
}
build(1,num,0);
int x=find(root,k+1),y=find(root,k+2);
splay(x,root);splay(y,ch[x][1]);
x=pos[(1+num)>>1];
ch[y][0]=x;
fa[x]=y;
pushup(y);pushup(root);
}
void del(int x,int y)
{
x=split(x,y);y=fa[x];
ch[y][0]=0;
recycle(x);
pushup(y);
pushup(root);
}
void modify(int x,int y,int val)
{
x=split(x,y);
tag[x]=1;
V[x]=val;
sum[x]=val*size[x];
mxl[x]=mxr[x]=max(sum[x],0);
mx[x]=max(sum[x],val);
pushup(fa[x]);
pushup(root);
}
void rever(int x,int y)
{
x=split(x,y);
if(!tag[x])
{
rev[x]^=1;
swap(ch[x][0],ch[x][1]);
swap(mxl[x],mxr[x]);
pushup(fa[x]);pushup(root);
}
}
int query_sum(int x,int y)
{
x=split(x,y);
return sum[x];
}
int main()
{
int n=read(),Q=read();
register int i;
for(i=1;i<=n;++i)
V[i+1]=read(),pos[i]=i;
pos[n+1]=n+1;
pos[n+2]=n+2;
V[1]=V[n+2]=-inf;
build(1,n+2,0);
root=(n+3)>>1;sz=n+2;
V[0]=mx[0]=-0X3f3f3f3f;
char opt[10];
register int k,num,val;int cnt=0;
while(Q--)
{
scanf("%s",opt);
switch(opt[0])
{
case 'I':
k=read();num=read();
insert(k,num);
break;
case 'D':
k=read();num=read();
del(k,k+num-1);
break;
case 'M':
if(opt[2]=='K')
{
k=read();num=read();val=read();
modify(k,k+num-1,val);
}
else
print(mx[root]),puts("");
break;
case 'R':
k=read();num=read();
rever(k,k+num-1);
break;
case 'G':
k=read();num=read();
print(query_sum(k,k+num-1));puts("");
break;
}
}
return 0;
}
/*
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
-1
10
1
10
*/
相关文章推荐
- BZOJ 1500 [NOI2005]维修数列(splay)
- BZOJ 1500 NOI2005 维修数列 Splay
- BZOJ 1500 【NOI2005 D1T2】 维修数列 Splay
- 【BZOJ1500】[NOI2005]维修数列【Splay】
- bzoj1500 [NOI2005]维修数列(splay)
- [BZOJ1500]NOI2005 维修数列|splay
- BZOJ1500: [NOI2005]维修数列 Splay维护序列
- BZOJ 1500([NOI2005]维修数列-Splay的数列维护)
- [BZOJ1500][NOI2005]维修数列(splay)
- _bzoj1500 [NOI2005]维修数列【真·Splay】
- [BZOJ1500][NOI2005][Splay]维修数列
- bzoj 1500: [NOI2005]维修数列(splay)
- BZOJ 1500 [NOI2005]维修数列 (splay)
- bzoj1500 [NOI2005]维修数列 splay
- BZOJ 1500: [NOI2005]维修数列( splay )
- [bzoj1500][NOI2005]维修数列——splay
- 【splay】[noi2005] bzoj1500 维修数列
- BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】
- 【splay】BZOJ 1500: [NOI2005]维修数列
- 【BZOJ1500】【NOI2005】维修数列(Splay)