• BZOJ 1500 洛谷2042维护序列题解


    BZ链接

    洛谷链接

    这道题真是丧心病狂。。。。

    应该很容易就可以看出做法,但是写代码写的.......

    思路很简单,用一个平衡树维护一下所有的操作就好了,重点讲解一下代码的细节

    首先如果按照常规写法的话,splay的节点要开到4000000,

    直接炸飞,

    由于任意时刻splay中的节点最多只有500000个,我们只需要开500000个节点就好了

    然后将没有用的节点回收起来,下一次插入是插入到这些节点中

    然后就是插入是将要插入的所有数字build成一颗平衡树,直接接在要插入的位置,这样会快很多

    维护最大子段和与线段树维护最大子段和方法一样,维护以包含左端点且以左端点开头的最大字段和,以及以右端点结尾的最大字段和

    还有自身的最大子段和,然后就可以通过左右儿子的信息快速算出当前节点的信息了

    具体细节可以看代码

    # include<cstdio>
    # include<iostream>
    # include<cmath>
    # include<algorithm>
    # include<cstring>
    # include<queue>
    using namespace std;
    const int inf = 0xfffffff;
    const int mn = 500005;
    int n,m,a[mn];
    struct Splay
    {
        int son[mn][2],fa[mn],sum[mn],id[mn],siz[mn];
        int v[mn],mx[mn],lx[mn],rx[mn],root,cnt;
        bool rev[mn],tag[mn];
        //v[x]为自身的权值
        //rev为翻转标记,sum为和,mx为最大子段和
        queue<int> q;
        //记录无用的编号
       void updown(int x)
        {
            int l=son[x][0],r=son[x][1];
            sum[x]=sum[l]+sum[r]+v[x];
            siz[x]=siz[l]+siz[r]+1;
            mx[x]=max(mx[l],max(mx[r],rx[l]+v[x]+lx[r]));
            lx[x]=max(lx[l],sum[l]+lx[r]+v[x]);
            rx[x]=max(rx[r],sum[r]+rx[l]+v[x]);
        }
        void pushdown(int x)
        {
            int l=son[x][0],r=son[x][1];
            if(tag[x])
            {
                tag[x]=rev[x]=0;
                if(l) tag[l]=1,v[l]=v[x],sum[l]=v[x]*siz[l];
                if(r) tag[r]=1,v[r]=v[x],sum[r]=v[x]*siz[r];
                if(v[x]>=0)
                {
                    if(l) mx[l]=lx[l]=rx[l]=sum[l];
                    if(r) mx[r]=lx[r]=rx[r]=sum[r];
                }
                else
                {
                    if(l) mx[l]=v[x],lx[l]=rx[l]=0;
                    if(r) mx[r]=v[x],lx[r]=rx[r]=0;
                }
            }
            if(rev[x])
            {
                rev[x]=0;
                rev[l]^=1;
                rev[r]^=1;
                swap(lx[l],rx[l]);
                swap(rx[r],lx[r]);
                swap(son[l][0],son[l][1]);
                swap(son[r][0],son[r][1]);
            }
        }
        void rotate(int x,int &k)
        {
            int y=fa[x],z=fa[y];
            int tmp;
            if(son[y][0]==x) tmp=1;
            else tmp=0;
            if(k==y)
                k=x;
            else
            {
                if(son[z][0]==y) son[z][0]=x;
                else son[z][1]=x;
            }
            son[y][tmp^1]=son[x][tmp],fa[son[y][tmp^1]]=y;
            son[x][tmp]=y;
            fa[y]=x,fa[x]=z;
            updown(y),updown(x);
        }
        void splay(int x,int &k)
        {
            while(x!=k)
            {
                int y=fa[x],z=fa[y];
                if(y!=k)
                {
                    if((son[z][0]==y) ^ (son[y][0]==x))
                        rotate(x,k);
                    else    rotate(y,k);
                }
                rotate(x,k);
            }
        }
        int find(int x,int rk)
        {
            pushdown(x);
            int l=son[x][0],r=son[x][1];
            if(siz[l]+1==rk) return x;
            else if(siz[l]>=rk) return find(l,rk);
            else return find(r,rk-siz[l]-1);
        }
        int split(int k,int tot)
        {
            int x=find(root,k),y=find(root,k+tot+1);
            //printf("QWQ
    ");
            splay(x,root),splay(y,son[x][1]);
            //printf("QWQ
    ");
            return son[y][0];
        }
        void recyc(int x)
        {
            int &l=son[x][0],&r=son[x][1];
            if(l) recyc(l);
            if(r) recyc(r);
            q.push(x);
            fa[x]=l=r=tag[x]=rev[x]=0;
        }
        void update()
        {
            int k,tot,val;
            scanf("%d%d%d",&k,&tot,&val);
            int x=split(k,tot),y=fa[x];
            v[x]=val;
            tag[x]=1;
            sum[x]=siz[x]*val;
            if(val>=0) lx[x]=rx[x]=mx[x]=sum[x];
            else lx[x]=rx[x]=0,mx[x]=v[x];
            updown(y);
            updown(fa[y]);
        }
        void rever()
        {
            int k,tot;
            scanf("%d%d",&k,&tot);
            int x=split(k,tot),y=fa[x];
            if(!tag[x])
            {
                rev[x]^=1;
                swap(lx[x],rx[x]);
                swap(son[x][0],son[x][1]);
                updown(y);
                updown(fa[y]);
            }
        }
        void build(int l,int r,int f)
        {
            int mid=(l+r)>>1,now=id[mid],pre=id[f];
            if(l==r)
            {
                mx[now]=sum[now]=a[l];
                tag[now]=rev[now]=0;
                lx[now]=rx[now]=max(a[l],0);
                siz[now]=1;
            }
            if(l<mid) build(l,mid-1,mid);
            if(r>mid) build(mid+1,r,mid);
            v[now]=a[mid];
            fa[now]=pre;
            updown(now);
            son[pre][(mid>=f)]=now;
        }
        void ins()
        {
            int k,tot;
            scanf("%d%d",&k,&tot);
            for(int i=1; i<=tot; i++)
                scanf("%d",&a[i]);
            for(int i=1; i<=tot; i++)
                if(!q.empty())
                {
                    id[i]=q.front();
                    q.pop();
                }
                else id[i]=++cnt;
            build(1,tot,0);//将要加入的数字建一颗splay
            int z=id[(1+tot)>>1];//取根
            int x=find(root,k+1),y=find(root,k+2);
            splay(x,root),splay(y,son[x][1]);
            fa[z]=y;
            son[y][0]=z;
            updown(y),updown(x);
        }
        void del()
        {
            int k,tot;
            scanf("%d%d",&k,&tot);
            int x=split(k,tot);
            int y=fa[x];
            recyc(x);
            son[y][0]=0;
            updown(y),updown(fa[y]);
        }
        void query()
        {
            int k,tot;
            scanf("%d%d",&k,&tot);
            int x=split(k,tot);
            //printf("sss
    ");
            printf("%d
    ",sum[x]);
        }
    } T;
    int main()
    {
        int x,y;
        char opt[20];
        scanf("%d%d",&n,&m);
        T.mx[0]=a[1]=a[n+2]=-inf;
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i+1]);
        for(int i=1; i<=n+2; i++)
            T.id[i]=i;
        T.cnt=n+2;
        T.build(1,n+2,0);
        T.root=(n+3)>>1;
        for(int i=1; i<=m; i++)
        {
            scanf("%s",opt);
            if(opt[0]=='I') T.ins();
            else if(opt[0]=='D') T.del();
            else if(opt[0]=='M' && opt[2]=='K') T.update();
            else if(opt[0]=='R') T.rever();
            else if(opt[0]=='G') T.query();
            else printf("%d
    ",T.mx[T.root]);
        }
        return 0;
    }
  • 相关阅读:
    高效管理,经理人须熟练运用的几个工具
    投资感情 收获人心
    忽如一夜入冬来
    贺嫦娥奔月
    正确处理人际关系,给自己做无形的投资
    观南溪豆干有感
    身在职场,请善待你的每一张白纸
    游一品天下有感
    增强影响力,如何提升你的“领袖气质”?
    oracle 创建表空间
  • 原文地址:https://www.cnblogs.com/logeadd/p/9350750.html
Copyright © 2020-2023  润新知