bzoj 1500 维修序列

Written with StackEdit.

Description

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

Input

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

Output

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

Sample Input

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

Sample Output

-1
10
1
10

Solution

  • 大数据结构题...敲完这道题保证神清气爽...
  • 本蒟蒻的做法是用一棵非旋\(treap\)维护这个数列.
  • \(split\)时按照\(size\)分割.这样分割出的区间是以下标排序的.
    • \(insert\):将给的数中序遍历,建成一棵小树后,再插入整颗树中.这样个人感性理解会比较方便.初始化也可以这样做.
    • \(delete\):将给的区间\(split\)出来,合并两旁的树.注意开内存栈回收空间.
    • \(make-same\):将给的区间\(split\)出来,打上对应的标记.
    • \(reverse\):将给的区间\(split\)出来,打上对应的标记.
    • \(getsum\):将给的区间\(split\)出来,直接返回\(pushup\)时维护的对应答案.
    • \(maxsum\):直接返回整颗树根节点\(pushup\)时维护的对应答案.
  • 这道题的细节部分主要在\(pushup\)函数内,而因为此题中最大子段和要求选出的子段不为空(题面没说清,根据数据感性理解的),所以初始化虚拟节点\(0\)的时候也是比较讲究的.具体可以看下面的代码.
  • 所以我为啥还要去学Splay呢.
#include<bits/stdc++.h>
#define inf 1e9
using namespace std;
typedef long long LoveLive;
inline int read()
{
    int out=0,fh=1;
    char jp=getchar();
    while ((jp>'9'||jp<'0')&&jp!='-')
        jp=getchar();
    if (jp=='-')
        {
            fh=-1;
            jp=getchar();
        }
    while (jp>='0'&&jp<='9')
        {
            out=out*10+jp-'0';
            jp=getchar();
        }
    return out*fh;
}
const int MAXN=5e5+10;
struct FhqTreap
{
    int x,y,z,p,q;
    int idx;
    int stk[MAXN],top;
    int w[MAXN];
    int root;
    struct node{
        int lson,rson,siz,key,weight;
        int rev,cov;//reverse and cover
        int sum,mx;//总和,最大子段和
        int lm,rm;//从左/右边开始的最大子段和 
    }treap[MAXN];
    FhqTreap()
        {
            idx=0;
            top=0;
            root=0;
            top=0;
            treap[0].sum=0;
            treap[0].siz=0;
            treap[0].mx=-inf;//特别注意.否则pushup最大子段和的时候,可能会出现空的子段. 
            treap[0].lm=0;
            treap[0].rm=0;
            treap[0].rev=0;
            treap[0].cov=inf;
        }
    #define rt treap[o]
    #define ls treap[treap[o].lson]
    #define rs treap[treap[o].rson]
    inline int newnode(int key)
        {
            int o=top?stk[top--]:++idx;
            rt.lson=rt.rson=0;
            rt.siz=1;
            rt.key=key;
            rt.weight=rand();
            rt.rev=0;
            rt.cov=inf;
            rt.sum=key;
            rt.mx=key;
            rt.lm=key;
            rt.rm=key;
            return o;
        }
    void pushup(int o)
        {
            if(!o)
                return;
            rt.siz=ls.siz+rs.siz+1;
            rt.sum=ls.sum+rs.sum+rt.key;
            rt.lm=rt.key;
            rt.lm=max(ls.lm,max(ls.sum+rt.key,ls.sum+rt.key+rs.lm));
            rt.rm=rt.key;
            rt.rm=max(rs.rm,max(rs.sum+rt.key,rs.sum+rt.key+ls.rm));
            rt.mx=rt.key;
            rt.mx=max((ls.rm>0?ls.rm:0)+rt.key+(rs.lm>0?rs.lm:0),max(ls.mx,rs.mx));//若子节点不存在,mx赋为-inf,强制选择了rt,保证不为空. 
        }
    void upend(int o)
        {
            swap(rt.lson,rt.rson);
            swap(rt.lm,rt.rm);
            rt.rev^=1;  
        }
    void cover(int o,int val)
        {
            rt.key=val;
            rt.sum=rt.siz*val;
            rt.mx=max(rt.sum,val);//字段长度至少为1
            rt.lm=max(rt.sum,0);// remained to be updated
            rt.rm=max(rt.sum,0); 
            rt.cov=val;
        }
    void pushdown(int o)
        {
            if(rt.rev)
                {
                    if(rt.lson)
                        upend(rt.lson);
                    if(rt.rson)
                        upend(rt.rson);
                }
            if(rt.cov!=inf)
                {
                    if(rt.lson)
                        cover(rt.lson,rt.cov);
                    if(rt.rson)
                        cover(rt.rson,rt.cov);
                }
            rt.rev=0;
            rt.cov=inf;
        }
    void recover(int o)
        {
            if(!o)
                return;
            stk[++top]=o;
            recover(rt.lson);
            recover(rt.rson);
        }
    void split(int &x,int &y,int k,int o)//按子树大小分,前k个分到x中,其余y中 
        {
            if(!o)
                x=y=0;
            else
                {
                    pushdown(o);
                    if(k<=ls.siz)
                        {
                            y=o;
                            split(x,rt.lson,k,rt.lson);
                        }
                    else
                        {
                            x=o;
                            split(rt.rson,y,k-ls.siz-1,rt.rson);
                        }
                    pushup(o);
                }
        }
    int merge(int x,int y)
        {
            if(x==0 || y==0)
                return x+y;
            pushdown(x);
            pushdown(y);
            if(treap[x].weight<treap[y].weight)
                {
                    treap[x].rson=merge(treap[x].rson,y);
                    pushup(x);
                    return x;
                }
            else
                {
                    treap[y].lson=merge(x,treap[y].lson);
                    pushup(y);
                    return y;
                }
        }
    int BuildTree(int l,int r)//以w[l]~w[r]建树,返回树根标号 
        {
            if(l>r)
                return 0;
            int mid=(l+r)>>1;
            int o=newnode(w[mid]);
            rt.lson=BuildTree(l,mid-1);
            rt.rson=BuildTree(mid+1,r);
            pushup(o);
            return o;
        }
    int getdata(int tot)
        {
            for(int i=1;i<=tot;++i)
                w[i]=read();
            return BuildTree(1,tot);
        }
    void ins(int pos,int tot)
        {
            int o=getdata(tot);
            split(x,y,pos,root);
            x=merge(x,o);
            root=merge(x,y);
        }
    void del(int pos,int tot)
        {
            split(x,y,pos-1,root);
            split(p,q,tot,y);
            root=merge(x,q);
            recover(p);
        }
    void update(int pos,int tot,int c)
        {
            split(x,y,pos-1,root);
            split(p,q,tot,y);
            cover(p,c);
            root=merge(x,merge(p,q));
        }
    void rev(int pos,int tot)
        {
            split(x,y,pos-1,root);
            split(p,q,tot,y);
            upend(p);
            root=merge(x,merge(p,q));
        }
    int getsum(int pos,int tot)
        {
            split(x,y,pos-1,root);
            split(p,q,tot,y);
            int res=treap[p].sum;
            root=merge(x,merge(p,q));
            return res;
        }
    int maxsum()
        {
            return treap[root].mx;
        }
    void pr(int o)
        {
            if(!o)
                return;
            pr(rt.lson);
            printf("%d ",rt.key);
            pr(rt.rson);
        }
    void print()
        {
            pr(root);
            puts("");
        }
}T;
int n,m;
int main()
{
    srand(time(NULL));
    n=read(),m=read();
    T.ins(0,n);
//  T.print();
    char op[50];
    int pos,tot,c;
    for(int i=1;i<=m;++i)
        {
            scanf("%s",op);
            if(op[0]=='I')
                {
                    pos=read();
                    tot=read();
                    T.ins(pos,tot);
                }
            else if(op[0]=='D')
                {
                    pos=read();
                    tot=read();
                    T.del(pos,tot);
                }
            else if(op[0]=='M' && op[2]=='K')
                {
                    pos=read();
                    tot=read();
                    c=read();
                    T.update(pos,tot,c);
                }
            else if(op[0]=='R')
                {
                    pos=read();
                    tot=read();
                    T.rev(pos,tot);
                }
            else if(op[0]=='G')
                {
                    pos=read();
                    tot=read();
                    int ans=T.getsum(pos,tot);
                    printf("%d\n",ans);
                }
            else if(op[0]=='M' && op[2]=='X')
                {
                    int ans=T.maxsum();
                    printf("%d\n",ans);
                }
        }
    return 0;
}

转载于:https://www.cnblogs.com/jklover/p/10110950.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值