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\n",query(st,len));
        }else if(s[2]=='X')
        {
          	printf("%d\n",tree[rot].maxval);
        }else
        {
            int st=read(),len=read(),v=read();
            changesame(st,len,v);
        }
    }
    return 0;
}

 

posted @ 2018-09-15 16:45  lleozhang  Views(155)  Comments(0Edit  收藏  举报
levels of contents