• 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();
            }
        }
    }
    
  • 相关阅读:
    给你的博客园加个面板娘!
    idea实现简单热部署
    idea 上传svn忽略文件
    谈一谈AOP面向切面编程
    做一个自定义注解
    使用aop切面编写日志模块
    数据结构之链表
    数据结构之队列
    数据结构之栈
    数据结构之线性表
  • 原文地址:https://www.cnblogs.com/suika/p/8592949.html
Copyright © 2020-2023  润新知