维护序列NOI2005
调了一个下午
最近做题都这样吧,思路很简单,代码很繁琐
要努力提高代码能力
细节太多很恶心;
详细地说一说吧
- Pushup
- 维护最大连续前缀和ls
- 最大连续后缀和rs
- 以及最大子序列和ms
int l=t[x].ch[0],r=t[x].ch[1];
size[x]=size[l]+size[r]+1;
ls[x]=max(ls[l],sum[l]+val[x]+ls[r]);
rs[x]=max(rs[r],sum[r]+val[x]+rs[l]);
ms[x]=max(ms[l],max(ms[r],rs[l]+ls[r]+val[x]));
sum[x]=sum[l]+sum[r]+val[x];
- Pushdown
- lazy数组表示是否make_same,因为same值有可能为0
- 并且因为lazy后rev无用
- ls[r]如果是负数,还不如不加(0)
- rev时:ls[x]与rs[x]也要交换
if(lazy[x])
if(lazy[x])
{
int l=t[x].ch[0],r=t[x].ch[1];
if(l)
{
lazy[l]=1;val[l]=val[x];sum[l]=size[l]*val[x];
ls[l]=rs[l]=max(sum[l],0);ms[l]=max(sum[l],val[x]);
}
if(r)
{
lazy[r]=1;val[r]=val[x];sum[r]=size[r]*val[x];
ls[r]=rs[r]=max(sum[r],0);ms[r]=max(sum[r],val[x]);
}
rev[x]=lazy[x]=0;
}
else if(rev[x])
{
int l=t[x].ch[0],r=t[x].ch[1];
rev[l]^=1;rev[r]^=1;
swap(ls[l],rs[l]);swap(ls[r],rs[r]);
swap(t[l].ch[1],t[l].ch[0]);swap(t[r].ch[0],t[r].ch[1]);
rev[x]=0;
}
- Build
- 回收机制使用,注意清空
- 叶子点赋值
int build(int l,int r,int f)
{
if(l>r) re 0;
int x,mid=(l+r)>>1;
if(top)
{
x=q[top];--top;
lazy[x]=rev[x]=0;
}
else x=++tot;
fa[x]=f;val[x]=num[mid];
t[x].ch[0]=build(l,mid-1,x);t[x].ch[1]=build(mid+1,r,x);
if(l==r)
{
ms[x]=sum[x]=num[mid];
ls[x]=rs[x]=max(num[mid],-1);
size[x]=1;
}
pushup(x);
re x;
}
- Split
- 就是将所求区间弄到根节点的右子树的左儿子里,返回左儿子
inline int split(int l,int r)
{
l=kth(l);
r=kth(r+1);
splay(l,0);
splay(r,l);
re t[r].ch[0];
}
- INSERT
- 建一颗平衡树,放在右儿子的左子树里
因为它的左儿子(0)可能没有左子树
inline void INSERT(int posi,int y)
{
inc(i,1,y)rd(num[i]);
int nrt=build(1,y,0);
int x=kth(posi+1),z=kth(posi+2);
splay(x,0);splay(z,x);
t[z].ch[0]=nrt;
fa[nrt]=z;
pushup(z);pushup(x);
}
- DELETE
- 记录一下垃圾编号,回收
- 前趋操作
if(s[0]!='M'||s[2]!='X')
rd(posi),rd(toto);
if(s[0]=='I')//insert
{
INSERT(posi,toto);
}
else if(s[0]=='D')//delete
{
x=split(posi,toto+posi);
DELETE(x);
t[fa[x]].ch[0]=0;//清除其在父节点信息
pushup(fa[x]);//更新
pushup(fa[fa[x]]);//更新至根节点
}
else if(s[0]=='R')//reverse
{
x=split(posi,posi+toto);
if(!lazy[x])
{
//初始修改
rev[x]^=1;
swap(t[x].ch[0],t[x].ch[1]);
swap(ls[x],rs[x]);
pushup(fa[x]),pushup(fa[fa[x]]);//更新至根节点
}
}
else if(s[2]=='K')//make_same
{
rd(c);
x=split(posi,posi+toto);
//初始修改
lazy[x]=1;
val[x]=c;
sum[x]=c*size[x];
if(c>0)
ls[x]=rs[x]=ms[x]=sum[x];
else
{
ls[x]=rs[x]=0;
ms[x]=c;
}
pushup(fa[x]);pushup(fa[fa[x]]);//更新至根节点
}
else
{
if(s[0]=='G')//get_sum
{
x=split(posi,toto+posi);
printf("%d\n",sum[x]);
}
else printf("%d\n",ms[rt]);//max_sum
}
完整代码
#include<bits/stdc++.h>
#define re return
#define MAX(a,b) (a)>(b)?(a):(b)
#define inc(i,l,r) for(int i=l;i<=r;++i)
const int maxn=500005;
template<typename T>inline void rd(T&x)
{
char c;bool f=0;
while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
x=c^48;
while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
if(f)x=-x;
}
using namespace std;
int rt,tot,q[maxn],top,n,m,num[maxn],fa[maxn];
int sum[maxn],size[maxn],val[maxn],lazy[maxn],rev[maxn],ls[maxn],rs[maxn],ms[maxn];
struct node{
int ch[2];
}t[maxn];
inline void pushup(int x)
{
int l=t[x].ch[0],r=t[x].ch[1];
size[x]=size[l]+size[r]+1;
ls[x]=max(ls[l],sum[l]+val[x]+ls[r]);
rs[x]=max(rs[r],sum[r]+val[x]+rs[l]);
ms[x]=max(ms[l],max(ms[r],rs[l]+ls[r]+val[x]));
sum[x]=sum[l]+sum[r]+val[x];
}
inline void pushdown(int x)
{
if(lazy[x])
{
int l=t[x].ch[0],r=t[x].ch[1];
if(l){lazy[l]=1;val[l]=val[x];sum[l]=size[l]*val[x];ls[l]=rs[l]=max(sum[l],-1);ms[l]=max(sum[l],val[x]);}
if(r){lazy[r]=1;val[r]=val[x];sum[r]=size[r]*val[x];ls[r]=rs[r]=max(sum[r],-1);ms[r]=max(sum[r],val[x]);}
rev[x]=lazy[x]=0;
}
else if(rev[x])
{
int l=t[x].ch[0],r=t[x].ch[1];
rev[l]^=1;rev[r]^=1;
swap(ls[l],rs[l]);swap(ls[r],rs[r]);
swap(t[l].ch[1],t[l].ch[0]);swap(t[r].ch[0],t[r].ch[1]);
rev[x]=0;
}
}
inline bool chk(int x){re t[fa[x]].ch[1]==x;}
inline void rotate(int x)
{
int y=fa[x],z=fa[y],k=chk(x),w=t[x].ch[k^1];
t[y].ch[k]=w;fa[w]=y;
t[z].ch[chk(y)]=x;fa[x]=z;
t[x].ch[k^1]=y;fa[y]=x;
pushup(y);pushup(x);
}
inline void splay(int x,int goal=0)
{
while(fa[x]!=goal)
{
int y=fa[x],z=fa[y];
if(z!=goal)
chk(x)==chk(y)?rotate(y):rotate(x);
rotate(x);
}
if(!goal)rt=x;
}
int build(int l,int r,int f)
{
if(l>r) re 0;
int x,mid=(l+r)>>1;
if(top)
{
x=q[top];--top;
lazy[x]=rev[x]=0;
}
else x=++tot;
fa[x]=f;val[x]=num[mid];
t[x].ch[0]=build(l,mid-1,x);t[x].ch[1]=build(mid+1,r,x);
if(l==r)
{
ms[x]=sum[x]=num[mid];
ls[x]=rs[x]=max(num[mid],-1);
size[x]=1;
}
pushup(x);
re x;
}
inline int kth(int k)
{
int u=rt;
while(1)
{
pushdown(u);
int y=t[u].ch[0];
if(k>size[y]+1)k=k-1-size[y],u=t[u].ch[1];
else if(k<=size[y])u=t[u].ch[0];
else re u;
}
}
inline int split(int l,int r)
{
l=kth(l);
r=kth(r+1);
splay(l,0);
splay(r,l);
re t[r].ch[0];
}
inline void INSERT(int posi,int y)
{
inc(i,1,y)rd(num[i]);
int nrt=build(1,y,0);
int x=kth(posi+1),z=kth(posi+2);
splay(x,0);splay(z,x);
t[z].ch[0]=nrt;
fa[nrt]=z;
pushup(z);pushup(x);
}
inline void DELETE(int x)
{
q[++top]=x;
if(t[x].ch[0])DELETE(t[x].ch[0]);
if(t[x].ch[1])DELETE(t[x].ch[1]);
}
inline void dfs(int x)
{
pushdown(x);
if(t[x].ch[0])dfs(t[x].ch[0]);
printf("%d %d\n",x,val[x]);
if(t[x].ch[1])dfs(t[x].ch[1]);
}
/*inline void debug()
{
printf("序列:::::\n");
dfs(rt);
printf("\n\nrt:%d\n",rt);
inc(i,1,14)
{
int x=i;
printf("--------------------------------------\n");
printf("x:%d\n",x);
printf("ch[0]:%d\n",t[x].ch[0]);
printf("ch[1]:%d\n",t[x].ch[1]);
printf("ls:%d\n",ls[x]);
printf("rs:%d\n",rs[x]);
printf("ms:%d\n",ms[x]);
printf("sum:%d\n",sum[x]);
printf("size:%d\n",size[x]);
printf("val:%d\n",val[x]);
printf("lazy:%d\n",lazy[x]);
printf("rev:%d\n",rev[x]);
}
}
*/
int main()
{
int cnt=0;
char s[25];
rd(n),rd(m);
inc(i,2,n+1)rd(num[i]);
num[1]=num[n+2]=ms[0]=-2e9;
rt=build(1,n+2,0);
int x,posi,toto,c;
inc(i,1,m)
{
scanf("%s",s);
if(s[0]!='M'||s[2]!='X')
rd(posi),rd(toto);
if(s[0]=='I')
{
INSERT(posi,toto);
}
else if(s[0]=='D')
{
x=split(posi,toto+posi);
DELETE(x);
t[fa[x]].ch[0]=0;
pushup(fa[x]);
pushup(fa[fa[x]]);
}
else if(s[0]=='R')
{
x=split(posi,posi+toto);
if(!lazy[x])
{
rev[x]^=1;
swap(t[x].ch[0],t[x].ch[1]);
swap(ls[x],rs[x]);
pushup(fa[x]),pushup(fa[fa[x]]);
}
}
else if(s[2]=='K')
{
rd(c);
x=split(posi,posi+toto);
lazy[x]=1;
val[x]=c;
sum[x]=c*size[x];
if(c>0)
ls[x]=rs[x]=ms[x]=sum[x];
else
{
ls[x]=rs[x]=0;
ms[x]=c;
}
pushup(fa[x]);pushup(fa[fa[x]]);
}
else
{
if(s[0]=='G')
{
x=split(posi,toto+posi);
printf("%d\n",sum[x]);
}
else printf("%d\n",ms[rt]);
}
}
re 0;
}