zoukankan      html  css  js  c++  java
  • SPLAY,LCT学习笔记(二)

    能够看到,上一篇的代码中有一段叫做find我没有提到,感觉起来也没有什么用,那么他的存在意义是什么呢?

    接下来我们来填一下这个坑

    回到我们的主题:NOI 2005维修数列

    我们刚刚讨论了区间翻转的操作方法,接下来我们来考虑区间插入和区间删除的方法。

    有了上一篇的铺垫,大家应该能看都,这两个操作方法是一致的,就是将区间前驱转到根,后继转到根的右节点。

    所以当我们插入一段区间的时候,我们还是把这个区间的前驱和后继转上去,然后把这段区间插到左子树就可以了

    等等,怎么插?

    一个一个往上扔?

    这显然是不合理的。

    合理的方法是,将所有数据先建成一棵树,然后直接把这棵树挂到左子节点上即可。

    可是这样时间不会爆吗?

    当然不会!

    为什么?

    我们稍微分析一下,每次建树都是O(nlog2n)的,而插入数字总数不超过4000000,也就是说,即使我们一次性将这些数全插进去,也仅仅会有点卡常

    何况正常情况下这么多东西不会一口气插进去,所以是完全不必担心时间炸掉的。

    那么删除一段区间也是同理了。

    再往后,就是区间赋值了。

    区间赋值和区间翻转很接近,但是如果进行了区间赋值,那区间翻转就没有进行的必要了,所以操作的时候注意一下顺序就好。

    然后是维护区间和和维护最大子段和

    区间求和操作类似线段树,我们用一个点维护他子树的和,向上更新即可

    最大子段和类似小白逛公园,由维护左联通,右联通和全区间的最优解,向上合并即可

    (所以有人吐槽,说这题是1/6的线段树,1/6小白逛公园,1/6文艺平衡树,还有1/2不知道什么玩意的东西)

    还需要一些细节问题:

    虽然说要扔进去4000000个数,但事实上,一个序列中不过500000个数,所以SPLAY空间开到500000左右就行

    可是剩下那些如果直接扔就立刻RE啦

    所以我们开一个队列,把原来删除的数的编号保存起来,做一个清理垃圾的机制,这样就可以保证空间不爆炸了。

    那么这样的话,每个根的编号就会有变化,所以我们要用一个映射getid,记录多余的编号

    可是如果这么操作,编号是很混乱的,所以我们就需要上面提到的find函数来查到这个端点在SPLAY中真实的根。

    最后是恶心的代码...

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define INF 0x3f3f3f3f
    #define ls tree[rt].lson
    #define rs tree[rt].rson
    using namespace std;
    struct SPLAY
    {
        int lson;
        int rson;
        int maxval;
        int maxls;
        int maxrs;
        int s;
        int val;
        bool ctag;
        bool ttag;
        int fa;
        int huge;
    }tree[1000005];
    int getid[500005]; 
    int a[500005];
    int cnt=0;
    int rot;
    int n,m;
    char s[10];
    queue <int> M;
    inline int read()
    {
        int f=1,x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void update(int rt)
    {
        tree[rt].s=tree[ls].s+tree[rs].s+tree[rt].val;
        tree[rt].huge=tree[ls].huge+tree[rs].huge+1;
        tree[rt].maxval=max(tree[ls].maxval,max(tree[rs].maxval,tree[ls].maxrs+tree[rs].maxls+tree[rt].val));
        tree[rt].maxls=max(tree[ls].maxls,tree[ls].s+tree[rt].val+tree[rs].maxls);
        tree[rt].maxrs=max(tree[rs].maxrs,tree[rs].s+tree[rt].val+tree[ls].maxrs);
    }
    void cleanrubbish(int rt)
    {
        if(ls)
        {
            cleanrubbish(ls);
        }
        if(rs)
        {
            cleanrubbish(rs);
        }
        M.push(rt);
        tree[rt].ttag=tree[rt].ctag=tree[rt].fa=ls=rs=0;
    }
    void pushdown(int rt)
    {
        if(tree[rt].ctag)
        {
            tree[rt].ctag=tree[rt].ttag=0;
            if(ls)
            {
                tree[ls].s=tree[rt].val*tree[ls].huge;
                tree[ls].ctag=1;
                tree[ls].val=tree[rt].val;
            }
            if(rs)
            {
                tree[rs].s=tree[rt].val*tree[rs].huge;
                tree[rs].ctag=1;
                tree[rs].val=tree[rt].val;
            }
            if(tree[rt].val>=0)
            {
                if(ls)
                {
                    tree[ls].maxval=tree[ls].maxls=tree[ls].maxrs=tree[ls].s;
                }
                if(rs)
                {
                    tree[rs].maxval=tree[rs].maxls=tree[rs].maxrs=tree[rs].s;
                }
            }else
            {
                if(ls)
                {
                    tree[ls].maxls=tree[ls].maxrs=0;
                    tree[ls].maxval=tree[ls].val;
                }
                if(rs)
                {
                    tree[rs].maxls=tree[rs].maxrs=0;
                    tree[rs].maxval=tree[rs].val;
                }
            }
        }
        if(tree[rt].ttag)
        {
            tree[rt].ttag=0;
            tree[ls].ttag^=1;
            tree[rs].ttag^=1;
            swap(tree[ls].maxls,tree[ls].maxrs);
            swap(tree[rs].maxls,tree[rs].maxrs);
            swap(tree[ls].lson,tree[ls].rson);
            swap(tree[rs].lson,tree[rs].rson);
        }
    }
    int findf(int rt,int v)
    {
        pushdown(rt);
        if(tree[ls].huge+1==v)
        {
            return rt;
        }else if(tree[ls].huge>=v)
        {
            return findf(ls,v);
        }else
        {
            return findf(rs,v-tree[ls].huge-1);
        }
    }
    void rotate(int st,int &to)
    {
        int v1=tree[st].fa;
        int v2=tree[v1].fa;
        int ltyp;
        if(tree[v1].rson==st)
        {
            ltyp=1;
        }else
        {
            ltyp=0;
        }
        if(v1==to)
        {
            to=st;
        }else
        {
            if(tree[v2].lson==v1)
            {
                tree[v2].lson=st;
            }else
            {
                tree[v2].rson=st;
            }
        }
        if(ltyp)
        {
            tree[tree[st].lson].fa=v1;
            tree[v1].fa=st;
            tree[v1].rson=tree[st].lson;
            tree[st].lson=v1;
            tree[st].fa=v2;
        }else
        {
            tree[tree[st].rson].fa=v1;
            tree[v1].fa=st;
            tree[v1].lson=tree[st].rson;
            tree[st].rson=v1;
            tree[st].fa=v2;
        }
        update(v1);
        update(st);
    }
    void splay(int st,int &to)
    {
        while(st!=to)
        {
            int v1=tree[st].fa;
            int v2=tree[v1].fa;
            if(v1!=to)
            {
                if((tree[v2].lson==v1&&tree[v1].lson!=st)||(tree[v2].rson==v1&&tree[v1].rson!=st))
                {
                    rotate(st,to);
                }else
                {
                    rotate(v1,to);
                }
            }
            rotate(st,to);
        }
    }
    int split(int st,int len)
    {
        int v1=findf(rot,st);
        int v2=findf(rot,st+len+1);
        splay(v1,rot);
        splay(v2,tree[v1].rson);
        return tree[v2].lson;
    }
    
    void reverse(int st,int len)
    {
        int v1=split(st,len);
        if(!tree[v1].ctag)
        {
            tree[v1].ttag^=1;
            swap(tree[v1].lson,tree[v1].rson);
            swap(tree[v1].maxls,tree[v1].maxrs);
            update(tree[v1].fa);
            update(tree[tree[v1].fa].fa);
        }
    }
    void buildtree(int l,int r,int f)
    {
        int mid=(l+r)>>1;
        int v1=getid[mid];
        int v2=getid[f];
        if(l==r)
        {
            tree[v1].lson=tree[v1].rson=0;
            tree[v1].maxval=tree[v1].s=tree[v1].val=a[l];
            tree[v1].maxls=tree[v1].maxrs=max(tree[v1].s,0);
            tree[v1].ctag=tree[v1].ttag=0;
            tree[v1].huge=1;
        }
        if(mid>l)
        {
            buildtree(l,mid-1,mid);
        }
        if(mid<r)
        {
            buildtree(mid+1,r,mid);
        }
        tree[v1].val=a[mid];
        tree[v1].fa=v2;
        update(v1);
        if(mid<f)
        {
            tree[v2].lson=v1;
        }else
        {
            tree[v2].rson=v1;
        }
    }
    void ins(int st,int len)
    {
        for(int i=1;i<=len;i++)
        {
            a[i]=read();
        }
        for(int i=1;i<=len;i++)
        {
            if(!M.empty())
            {
                getid[i]=M.front();
                M.pop();
            }else
            {
                getid[i]=++cnt;
            }
        }
        buildtree(1,len,0);
        int v=getid[(1+len)>>1];
        int v1=findf(rot,st+1);
        int v2=findf(rot,st+2);
        splay(v1,rot);
        splay(v2,tree[rot].rson);
        tree[v2].lson=v;
        tree[v].fa=v2;
        update(v2);
        update(v1);
    }
    void del(int st,int len)
    {
        int v1=split(st,len);
        int f=tree[v1].fa;
        tree[f].lson=0;
        cleanrubbish(v1);
        update(f);
        update(tree[f].fa);
    }
    void changesame(int st,int len,int v)
    {
        int v1=split(st,len);
        tree[v1].val=v;
        tree[v1].ctag=1;
        tree[v1].s=tree[v1].huge*v;
        if(v>=0)
        {
            tree[v1].maxls=tree[v1].maxrs=tree[v1].maxval=tree[v1].s;
        }else
        {
            tree[v1].maxls=tree[v1].maxrs=0;
            tree[v1].maxval=v;
        }
        update(tree[v1].fa);
        update(tree[tree[v1].fa].fa);
    }
    int query(int st,int len)
    {
        int v1=split(st,len);
        return tree[v1].s;
    }
    int main()
    {
    //  freopen("data.in","r",stdin);
    //  freopen("my.out","w",stdout);
            n=read(),m=read();
        tree[0].maxval=a[1]=a[n+2]=-INF;
        for(int i=1;i<=n;i++)
        {
            a[i+1]=read();
            getid[i]=i;
        }
        getid[n+1]=n+1;
        getid[n+2]=n+2;
        buildtree(1,n+2,0);
        rot=(n+3)>>1,cnt=n+2;
        while(m--)
        {
            scanf("%s",s);
            if(s[0]=='I')
            {
                int st=read(),len=read();
                ins(st,len);
            }else if(s[0]=='D')
            {
                int st=read(),len=read();
                del(st,len);
            }else if(s[0]=='R')
            {
                int st=read(),len=read();
                reverse(st,len);
            }else if(s[0]=='G')
            {
                int st=read(),len=read();
                    printf("%d
    ",query(st,len));
            }else if(s[2]=='X')
            {
              	printf("%d
    ",tree[rot].maxval);
            }else
            {
                int st=read(),len=read(),v=read();
                changesame(st,len,v);
            }
        }
        return 0;
    }
  • 相关阅读:
    K近邻法
    决策树
    朴素贝叶斯
    Git学习笔记
    【原】maven web项目eclipse搭建
    三道面试题
    72-74 流的考点
    57-71 容器考点
    四 java web考点
    五 数据库考点
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10764216.html
Copyright © 2011-2022 走看看