BZOJ_1500_[NOI2005]维修数列_splay

BZOJ_1500_[NOI2005]维修数列_splay

题意:

分析:

节点维护从左开始的最大连续子段和,从右开始的最大连续子段和,区间的最大连续子段和

插入:重新建一棵树,把pos旋到根,把pos+1旋到根的右儿子,直接插到根的右儿子的左儿子上

删除:节点回收,用循环队列或者栈存一下删除的节点,新建的时候用。

修改和翻转正常做,这两个标记互不影响。记得翻转时左右儿子的信息都要交换。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000050
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (x==ch[f[x]][1])
int ch[N][2],f[N],siz[N],val[N],n,m;
int cov[N],turn[N],maxl[N],maxr[N],maxm[N];
int S[N],top,sum[N],rt,a[N],sz,tot;
int other_root;
char opt[20];
void clear(int x){if(!x)return ;ch[x][0]=ch[x][1]=f[x]=val[x]=siz[x]=sum[x]=turn[x]=maxl[x]=maxr[x]=maxm[x]=0;cov[x]=0x3f3f3f3f;}
void print(int p)
{
    if(!p)return ;
    if(ls)print(ls);
    printf("p=%d val[p]=%d
",p,val[p]);
    if(rs)print(rs);
}
int newnode(int v)
{
    int p;
    if(top)p=S[--top];
    else p=++tot;
    clear(p);
    val[p]=v;siz[p]=1;
    maxl[p]=maxr[p]=v>0?v:0;
    maxm[p]=v;
    return p;
}
void update(int p)
{
    if(!p)return ;
    siz[p]=siz[ls]+siz[rs]+1;
    sum[p]=sum[ls]+sum[rs]+val[p];
    maxl[p]=max(maxl[ls],sum[ls]+val[p]+maxl[rs]);
    maxr[p]=max(maxr[rs],sum[rs]+val[p]+maxr[ls]);
    maxm[p]=val[p];
    maxm[p]=max(max(maxm[p],maxm[ls]),maxm[rs]);
    maxm[p]=max(maxm[p],maxr[ls]+val[p]+maxl[rs]);  
}
void pushdown(int p)
{
    if(cov[p]!=0x3f3f3f3f)
    {
        int t=cov[p];
        cov[p]=0x3f3f3f3f;
        cov[ls]=cov[rs]=t;
        val[ls]=val[rs]=t;
        sum[ls]=siz[ls]*t;
        sum[rs]=siz[rs]*t;
        maxl[ls]=maxr[ls]=t>0?sum[ls]:0;
        maxm[ls]=t>0?sum[ls]:t;
        maxl[rs]=maxr[rs]=t>0?sum[rs]:0;
        maxm[rs]=t>0?sum[rs]:t;
    }
    if(turn[p])
    {
        swap(ls,rs);
        swap(maxl[ls],maxr[ls]);
        swap(maxl[rs],maxr[rs]);
        turn[ls]^=1;
        turn[rs]^=1;
        turn[p]=0;
    }
}
void rotate(int x)
{
    int y=f[x],z=f[y],k=get(x);
    ch[y][k]=ch[x][k^1];f[ch[y][k]]=y;
    ch[x][k^1]=y;f[y]=x;f[x]=z;
    if(z) ch[z][ch[z][1]==y]=x;
    update(y),update(x);
    if(rt==y)rt=x;
}
void splay(int x,int y)
{
    for(int fa;(fa=f[x])!=y;rotate(x))
        if(f[fa]!=y)
            rotate((get(x)==get(fa)) ? fa : x);
}
int find(int x)
{
    int p=rt;
    while(1)
    {
        pushdown(p);
        if(x<=siz[ls])p=ls;
        else
        {
            x-=siz[ls]+1;
            if(!x) return p;
            p=rs;
        }
    }
}
void print1()
{
    for(int i=1;i<=sz;i++){int p=find(i);printf("p=%d val[p]=%d
",p,val[p]);}   
}
void build(int fa,int l,int r)
{
    if(l>r)return ;
    int mid=l+r>>1;
    ch[fa][mid>fa]=mid;
    f[mid]=fa;
    val[mid]=a[mid-1];
    siz[mid]=1;
    build(mid,l,mid-1);
    build(mid,mid+1,r);
    update(mid);
}
void build_merge(int fa,int l,int r,int flg)
{
    if(l>r)return ;
    int mid=l+r>>1;
    int p=newnode(a[mid]);
    val[p]=a[mid];
    ch[fa][flg]=p;
    f[p]=fa;
    build_merge(p,l,mid-1,0);
    build_merge(p,mid+1,r,1);
    update(p);
}
void insert(int x,int cnt)
{
    int i;
    for(i=1;i<=cnt;i++) scanf("%d",&a[i]);
    sz+=cnt;
    int p=x+1;
    x=find(x);
    p=find(p);
    splay(x,f[rt]);
    splay(p,rt);
    build_merge(p,1,cnt,0);
}
void rec(int p)
{
    if(!p)return ;
    if(ls)rec(ls);
    ls=0;
    if(rs)rec(rs);
    rs=0;
    clear(p);
    S[top++]=p;
}
void del(int x,int p)
{
    x=find(x);
    p=find(p);
    splay(x,f[rt]);
    splay(p,rt);
    sz-=siz[ls];
    rec(ls);
    ls=0;
    update(p);update(x);
}
void modify(int x,int p,int c)
{
    x=find(x);
    p=find(p);
    splay(x,f[rt]);
    splay(p,rt);
    cov[ls]=c;
    val[ls]=c;
    sum[ls]=c*siz[ls];
    maxl[ls]=maxr[ls]=c>0?sum[ls]:0;
    maxm[ls]=c>0?sum[ls]:c;
    update(p);update(x);
}
void reverse(int x,int p)
{
    x=find(x);
    p=find(p);
    splay(x,f[rt]);
    splay(p,rt);
    turn[ls]^=1;
    swap(maxl[ls],maxr[ls]);
    update(p);update(x);
}
void getsum(int x,int p)
{
    x=find(x);
    p=find(p);
    splay(x,f[rt]);
    splay(p,rt);
    printf("%d
",sum[ls]);
}
void getmax_sum()
{
    int x=1,p=sz;
    x=find(x);
    p=find(p);
    splay(x,f[rt]);
    splay(p,rt);
    printf("%d
",maxm[ls]);
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(cov,0x3f,sizeof(cov));
    sz=n+2;tot=n+2;
    int i,x,y,z;
    for(i=1;i<=n;i++) scanf("%d",&a[i]); 
    build(0,1,n+2);
    rt=n+3>>1;
    for(i=1;i<=m;i++)
    {
        scanf("%s",opt);
        if(opt[2]=='S'){
            scanf("%d%d",&x,&y);
            insert(x+1,y);      
        }else if(opt[2]=='L'){
            scanf("%d%d",&x,&y);
            del(x,x+y+1);
        }else if(opt[2]=='K'){
            scanf("%d%d%d",&x,&y,&z);
            modify(x,x+y+1,z);
        }else if(opt[2]=='V'){
            scanf("%d%d",&x,&y);
            reverse(x,x+y+1);
        }else if(opt[2]=='T'){
            scanf("%d%d",&x,&y);
            getsum(x,x+y+1);
        }else{
            getmax_sum();
        }
    }
}
原文地址:https://www.cnblogs.com/suika/p/8592949.html