zoukankan      html  css  js  c++  java
  • BZOJ1500[NOI2005]维修数列——非旋转treap

    题目描述

    请写一个程序,要求维护一个数列,支持以下 6 种操作:
    请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格

    输入

    输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
    第2行包含N个数字,描述初始时的数列。
    以下M行,每行一条命令,格式参见问题描述中的表格。
    任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
    插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。

    输出

    对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

    样例输入

    9 8
    2 -6 3 5 1 -5 -3 6 3
    GET-SUM 5 4
    MAX-SUM
    INSERT 8 3 -5 7 2
    DELETE 12 1
    MAKE-SAME 3 3 2
    REVERSE 3 6
    GET-SUM 5 4
    MAX-SUM

    样例输出

    -1
    10
    1
    10

    提示

    这道题的区间操作十分全,无论是用非旋转treap还是splay写,都会有更深入的理解。

    讲一下每个操作的实现

    1、将插入的数再建一棵treap,然后把原treap断裂,把新建treap合并进去。

    2、把treap断裂成三部分,然后再把左右两部分合并。

    3、也是把treap断裂成三部分,把中间部分打标记,标记在合并时下传。

    4、和上面一样,也是断裂成三部分,中间打标记。

    5、断裂成三部分,输出中间部分根节点的子树和。

    6、直接输出根节点的最大连续子段和。

    最后不要忘了资源回收(回收节点编号)

    最后附上代码(有注释)

    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int num;
    int pos;
    int tot;//树的大小
    int root;//根节点
    int n,k,g;
    int x,y,z;
    int b,c,d;
    char ch[5];
    queue<int>q;//资源回收队列
    int a[200010];//插入序列及初始序列
    int m[500010];//区间最大子段和
    int s[500010];//翻转标记
    int f[500010];//修改标记
    int r[500010];//随机数
    int ls[500010];//左儿子
    int rs[500010];//右儿子
    int lm[500010];//子树区间中从左端点开始的最大连续子段和
    int rm[500010];//子树区间中以右端点结束的最大连续子段和
    int val[500010];//节点权值
    int sum[500010];//子树区间和
    int size[500010];//子树大小
    int INF=2147483647;
    int insert(int v)
    {
        int x;
        if(!q.empty())
        {
            x=q.front();
            q.pop();
        }
        else
        {
            x=++tot;
        }
        size[x]=1;
        ls[x]=rs[x]=s[x]=0;
        f[x]=INF;
        r[x]=rand();
        val[x]=sum[x]=v;
        lm[x]=rm[x]=m[x]=v;
        return x;
    }
    void updata(int x)
    {
        if(!x)
        {
            return ;
        }
        size[x]=size[ls[x]]+size[rs[x]]+1;
        sum[x]=sum[ls[x]]+sum[rs[x]]+val[x];
        m[x]=max(max(0,rm[ls[x]])+val[x]+max(0,lm[rs[x]]),max(m[ls[x]],m[rs[x]]));
        lm[x]=max(lm[ls[x]],sum[ls[x]]+val[x]+max(0,lm[rs[x]]));
        rm[x]=max(rm[rs[x]],sum[rs[x]]+val[x]+max(0,rm[ls[x]]));
    }
    void change(int x,int v)
    {
        val[x]=v;
        sum[x]=size[x]*v;
        lm[x]=rm[x]=max(0,sum[x]);
        m[x]=max(val[x],sum[x]);
        f[x]=v;
    }
    void rotate(int x)
    {
        swap(ls[x],rs[x]);
        swap(lm[x],rm[x]);
        s[x]^=1;
    }
    void downdata(int x)
    {
        if(s[x])
        {
            if(ls[x])
            {
                rotate(ls[x]);
            }
            if(rs[x])
            {
                rotate(rs[x]);
            }
        }
        if(f[x]!=INF)
        {
            if(ls[x])
            {
                change(ls[x],f[x]);
            }
            if(rs[x])
            {
                change(rs[x],f[x]);
            }
        }
        s[x]=0;
        f[x]=INF;
    }
    int build(int l,int r)
    {
        if(l>r)
        {
            return 0;
        }
        int mid=(l+r)>>1;
        int v=a[mid];
        int x=insert(v);
        ls[x]=build(l,mid-1);
        rs[x]=build(mid+1,r);
        updata(x);
        return x;
    }
    void split(int now,int t,int &x,int &y)
    {
        if(!now)
        {
            x=y=0;
        }
        else
        {
            downdata(now);
            if(t<=size[ls[now]])
            {
                y=now;
                split(ls[now],t,x,ls[now]);
            }
            else
            {
                x=now;
                split(rs[now],t-size[ls[now]]-1,rs[now],y);
            }
            updata(now);
        }
    }
    int merge(int x,int y)
    {
        if(!x||!y)
        {
            return x+y;
        }
        downdata(x);
        downdata(y);
        if(r[x]<r[y])
        {
            rs[x]=merge(rs[x],y);
            updata(x);
            return x;
        }
        else
        {
            ls[y]=merge(x,ls[y]);
            updata(y);
            return y;
        }
    }
    void inque(int x)
    {
        if(!x)
        {
            return ;
        }
        q.push(x);
        inque(ls[x]);
        inque(rs[x]);
    }
    int main()
    {
        srand(16);
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        val[0]=m[0]=-INF;
        root=build(1,n);
        while(k--)
        {
            scanf("%s",ch);
            if(ch[0]=='I')
            {
                scanf("%d%d",&pos,&num);
                for(int i=1;i<=num;i++)
                {
                    scanf("%d",&a[i]);
                }
                z=build(1,num);
                split(root,pos,x,y);
                root=merge(merge(x,z),y);
            }
            else if(ch[0]=='D')
            {
                scanf("%d%d",&pos,&num);
                split(root,pos-1,x,y);
                split(y,num,b,c);
                root=merge(x,c);
                inque(b);
            }
            else if(ch[2]=='K')
            {
                scanf("%d%d%d",&pos,&num,&g);
                split(root,pos-1,x,y);
                split(y,num,b,c);
                change(b,g);
                root=merge(x,merge(b,c));
            }
            else if(ch[0]=='R')
            {
                scanf("%d%d",&pos,&num);
                split(root,pos-1,x,y);
                split(y,num,b,c);
                rotate(b);
                root=merge(x,merge(b,c));
            }
            else if(ch[0]=='G')
            {
                scanf("%d%d",&pos,&num);
                split(root,pos-1,x,y);
                split(y,num,b,c);
                printf("%d
    ",sum[b]);
                root=merge(x,merge(b,c));
            }
            else
            {
                printf("%d
    ",m[root]);
            }
        }
        return 0;
    }
  • 相关阅读:
    x+=y与x=x+y有什么区别?
    Linux下带宽流量工具iftop实践
    使用pinyin4j实现汉字转拼音
    Spring整合Velocity模版引擎
    Json工具类库之Gson实战笔记
    腾讯移动分析 签名代码示例
    Docker搭建Portainer可视化界面
    maven 打包 spring boot 生成docker 镜像
    Mysql 为什么要选择 B+Tree
    idea 添加 注释 配置
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/9218409.html
Copyright © 2011-2022 走看看