zoukankan      html  css  js  c++  java
  • Luogu P2042 [NOI2005]维护数列

    题目描述

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

    _

    输入输出格式

    输入格式:
    输入文件的第 1 行包含两个数 N 和 M,N 表示初始时数列中数的个数,M 表示要进行的操作数目。 第 2 行包含 N 个数字,描述初始时的数列。 以下 M 行,每行一条命令,格式参见问题描述中的表格

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

    输入输出样例

    输入样例#1:

    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:

    -1

    10

    1

    10

    说明

    你可以认为在任何时刻,数列中至少有 1 个数。

    输入数据一定是正确的,即指定位置的数在数列中一定存在。

    50%的数据中,任何时刻数列中最多含有 30 000 个数;

    100%的数据中,任何时刻数列中最多含有 500 000 个数。

    100%的数据中,任何时刻数列中任何一个数字均在[-1 000, 1 000]内。

    100%的数据中,M ≤20 000,插入的数字总数不超过 4 000 000 。

    分析

    复杂度 思维1 编程7

    本题思维上很简单,先判断使用平衡树,再用ls,rs维护最大和,之后挨个完成各个功能。注意节点需要回收利用。回收总复杂度O(n)。总体复杂度O(nlogn)。

    代码

    #include <cstdio>
    #include <cstdlib>
    #define rt ch[0][0]
    const int N=500000,S=N+100,inf=(1<<25)-1;
    int n,m,a[S],bin[S],ch[S][2],ls[S],rs[S],fa[S],su[S],sz[S],mx[S],add[S],rev[S];
    void rd(int &x)
    {
        x=0;char c=getchar(),t=1;
        while (c!='-' && (c<'0' || c>'9')) c=getchar();
        if (c=='-') t=-1,c=getchar();
        while (c>='0' && c<='9') x=(x<<3)+(x<<1)+(c-'0'),c=getchar();
        x*=t;
    }
    void init()
    {
        for (int i=0;i<=N;i++)
            bin[i]=i;
        bin[0]=1;
    
        rt=1;
    
        ls[0]=rs[0]=mx[0]=-inf;
        sz[0]=0;
    
        bin[0]=2;//use 1
        sz[1]=2;ch[1][1]=2;fa[1]=0;a[1]=-inf;add[1]=inf;
    
        bin[0]=3;//use 2
        sz[2]=1;fa[2]=1;add[2]=inf;a[2]=-inf;
    }
    inline int ma(int a,int b){if (a>b) return a;return b;}
    inline int ma3(int a,int b,int c){return ma(a,ma(b,c));}
    inline void swap(int &a,int &b){a^=b^=a^=b;}
    inline void up(int x)
    {
        int L=ch[x][0],R=ch[x][1];
        sz[x]=sz[L]+sz[R]+1;
        su[x]=su[L]+su[R]+a[x];
        ls[x]=ma3(ls[L],su[L]+a[x],su[L]+a[x]+ls[R]);
        rs[x]=ma3(rs[R],su[R]+a[x],su[R]+a[x]+rs[L]);
        int mid=ma(rs[L],0)+a[x]+ma(ls[R],0);
        mx[x]=ma3(mx[L],mx[R],mid);
        mx[x]=ma3(mx[x],ls[x],rs[x]);
    }
    inline void down(int x)
    {
        int &L=ch[x][0],&R=ch[x][1];
        if (rev[x])
        {
            if (L)
            {
                rev[L]^=1;
                swap(ch[L][0],ch[L][1]);
                swap(ls[L],rs[L]);
            }
            if (R)
            {
                rev[R]^=1;
                swap(ch[R][0],ch[R][1]);
                swap(ls[R],rs[R]);
            }
            rev[x]=0;
        }
        if (add[x]!=inf)
        {
            if (L)
            {
                add[L]=add[x];
                su[L]=add[L]*sz[L];
                a[L]=add[L];
                if (add[x]>0)
                    ls[L]=rs[L]=mx[L]=su[L];
                else
                    ls[L]=rs[L]=mx[L]=a[L];
            }
            if (R)
            {
                add[R]=add[x];
                su[R]=add[R]*sz[R];
                a[R]=add[R];
                if (add[x]>0)
                    ls[R]=rs[R]=mx[R]=su[R];
                else
                    ls[R]=rs[R]=mx[R]=a[R];
            }
            add[x]=inf;
        }
    }
    inline bool lor(int x){return ch[fa[x]][1]==x;}
    inline void link(int x,int fat,int o){fa[x]=fat;ch[fat][o]=x;}
    inline void rotate(int x)
    {
        int y=fa[x],r=fa[y];
        down(y);down(x);
        int rson=lor(y),yson=lor(x);
        link(ch[x][yson^1],y,yson);
        link(y,x,yson^1);
        link(x,r,rson);
        up(y);up(x);
    }
    void splay(int x,int to)
    {
        to=fa[to];
        while (fa[x]!=to)
        {
            if (fa[fa[x]]==to) rotate(x);
            else if (lor(x)==lor(fa[x])) rotate(fa[x]),rotate(x);
            else rotate(x),rotate(x);
        }
    }
    void build(int &k,int fat,int l,int r)
    {
        if (l>r)
        {
            k=0;
            return;
        }
        k=bin[bin[0]++];
        fa[k]=fat;
        int mid=(l+r)>>1;
        build(ch[k][0],k,l,mid-1);
        rd(a[k]);
        add[k]=inf;rev[k]=0;
        build(ch[k][1],k,mid+1,r);
        up(k);
    }
    void recycle(int k)
    {
        if (!k) return;
        recycle(ch[k][0]);
        a[k]=su[k]=ls[k]=rs[k]=mx[k]=fa[k]=add[k]=rev[k]=0;
        bin[--bin[0]]=k;
        recycle(ch[k][1]);
        ch[k][0]=ch[k][1]=0;
    }
    int find(int x)
    {
        int o=rt;
        while (o)
        {
            down(o);
            if (sz[ch[o][0]]+1==x)
                break;
            if (x<=sz[ch[o][0]])
                o=ch[o][0];
            else x-=sz[ch[o][0]]+1,o=ch[o][1];
        }
        return o;
    }
    void insert(int pos,int tot)
    {
        pos++;
        int bg=find(pos),ed=find(pos+1);
        splay(bg,rt);
        splay(ed,ch[bg][1]);
        build(ch[ed][0],ed,1,tot);
        up(ed);up(bg);
    }
    void del(int pos,int tot)
    {
        int bg=find(pos),ed=find(pos+tot+1);
        splay(bg,rt);splay(ed,ch[bg][1]);
        recycle(ch[ed][0]);
        ch[ed][0]=0;
        up(ed);up(bg);
    }
    void make_same(int pos,int tot,int x)
    {
        int bg=find(pos),ed=find(pos+tot+1);
        splay(bg,rt);splay(ed,ch[bg][1]);
        int o=ch[ed][0];
        add[o]=x;su[o]=x*sz[o];a[o]=x;
        if (x>0) ls[o]=rs[o]=mx[o]=su[o];
        else ls[o]=rs[o]=mx[o]=a[o];
        up(ed);up(bg);
    }
    void reverse(int pos,int tot)
    {
        int bg=find(pos),ed=find(pos+tot+1);
        splay(bg,rt);splay(ed,ch[bg][1]);
        down(bg);down(ed);
        int o=ch[ed][0];
        rev[o]=1;
        swap(ch[o][0],ch[o][1]);
        swap(ls[o],rs[o]);
        up(ed);up(bg);
    }
    void getsum(int pos,int tot)
    {
        int bg=find(pos),ed=find(pos+tot+1);
        splay(bg,rt);
        splay(ed,ch[bg][1]);
        int o=ch[ed][0];
        printf("%d
    ",su[o]);
    }
    int main()
    {
        rd(n);rd(m);
        init();
        build(ch[2][0],2,1,n);up(2);up(1);
        char op[10];int tot,pos,x;
        while (m--)
        {
            scanf("%s",op);
            if (op[2]=='X')//max_sum
                printf("%d
    ",mx[rt]);
            else
            {
                rd(pos);rd(tot);
                if (op[2]=='S')//Insert
                    insert(pos,tot);
                else if (op[2]=='L')
                    del(pos,tot);
                else if ('K'==op[2])
                {
                    scanf("%d",&x);
                    make_same(pos,tot,x);
                }
                else if ('V'==op[2])
                    reverse(pos,tot);
                else getsum(pos,tot);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    单调递增的数字
    合并K个升序链表
    ISO 8 自适应cell
    动态计算UITableViewCell高度
    APP上传
    多线程 GCD队列组
    多线程 线程之间的通信
    多线程 GCD
    多线程 线程同步问题
    多线程 线程的状态
  • 原文地址:https://www.cnblogs.com/Algebra-hy/p/11031141.html
Copyright © 2011-2022 走看看