Luogu P2042 [NOI2005]维护数列(平衡树)

P2042 [NOI2005]维护数列

题意

题目描述

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

P2042

输入输出格式

输入格式:

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

输出格式:

对于输入数据中的GET-SUMMAX-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\%\)的数据中,任何时刻数列中最多含有\(30000\)个数;

\(100\%\)的数据中,任何时刻数列中最多含有\(500000\)个数。

\(100\%\)的数据中,任何时刻数列中任何一个数字均在\([-1000,1000]\)内。

\(100\%\)的数据中,\(M\leq 20000\),插入的数字总数不超过\(4000000\)

思路

平衡树板子题(其实没有那么板),调试的难度还是很大的。

\(fhq\ Treap\)的线性建树是我从这题学到的新定西,直接放代码吧:

int build(int now)//新加入的点的数量
{
    stack<int>S;//主要思想是维护一个单调栈
    int last;
    for(int i=1;i<=now;i++)
    {
        int x=new_node(a[i]);last=0;//新建结点
        while(!S.empty()&&rnd(S.top())>rnd(x)) last=S.top(),update(S.top()),S.pop();//维护小根堆,寻找新结点的父节点
        if(!S.empty()) rs(S.top())=x;
        ls(x)=last,S.push(x);//把刚刚弹出的结点再接上
    }
    while(!S.empty()) last=S.top(),update(S.top()),S.pop();
    return last;//返回新建树的根
}

本题的第二个难点是内存回收,可以直接开一个队列记录被删除的点,新建结点时从队列中取就好了。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=5e5+5;
int n,m,rt,cnt,a[MAXN];
bool H[MAXN];
int read()
{
    bool f=true;int re=0;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=false;ch=getchar();}
    while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
    return f?re:-re;
}
struct Node
{
    int ls,rs,sz,val,rnd,sum;
    int sub_sum,left_sub_sum,right_sub_sum;
    int change_tag;
    bool reverse_tag;
    #define ls(a) node[a].ls
    #define rs(a) node[a].rs
    #define sz(a) node[a].sz
    #define val(a) node[a].val
    #define rnd(a) node[a].rnd
    #define sum(a) node[a].sum
    #define lsm(a) node[a].left_sub_sum
    #define rsm(a) node[a].right_sub_sum
    #define sub(a) node[a].sub_sum
    #define ctg(a) node[a].change_tag
    #define rtg(a) node[a].reverse_tag
}node[MAXN];
queue<int>dustbin;
int new_node(int k)
{
    int re;
    if(!dustbin.empty()) re=dustbin.front(),H[dustbin.front()]=false,dustbin.pop();
    else re=++cnt;
    ls(re)=rs(re)=0,sz(re)=1;
    val(re)=sum(re)=sub(re)=k;
    lsm(re)=rsm(re)=max(k,0);
    rnd(re)=rand();
    ctg(re)=INT_MAX,rtg(re)=false;
    return re;
}
void update(int now)
{
    if(ls(now)&&rs(now))
    {
        sz(now)=sz(ls(now))+sz(rs(now))+1;
        sum(now)=sum(ls(now))+sum(rs(now))+val(now);
        lsm(now)=max(lsm(ls(now)),sum(ls(now))+val(now)+lsm(rs(now)));
        rsm(now)=max(rsm(rs(now)),sum(rs(now))+val(now)+rsm(ls(now)));
        sub(now)=max(max(sub(ls(now)),sub(rs(now))),rsm(ls(now))+val(now)+lsm(rs(now)));
    }
    else if(ls(now))
    {
        sz(now)=sz(ls(now))+1;
        sum(now)=sum(ls(now))+val(now);
        lsm(now)=max(max(lsm(ls(now)),sum(ls(now))+val(now)),0);
        rsm(now)=max(0,val(now)+rsm(ls(now)));
        sub(now)=max(sub(ls(now)),rsm(ls(now))+val(now));
    }
    else if(rs(now))
    {
        sz(now)=sz(rs(now))+1;
        sum(now)=sum(rs(now))+val(now);
        rsm(now)=max(max(rsm(rs(now)),sum(rs(now))+val(now)),0);
        lsm(now)=max(0,val(now)+lsm(rs(now)));
        sub(now)=max(sub(rs(now)),lsm(rs(now))+val(now));
    }
    else
    {
        sz(now)=1,sum(now)=sub(now)=val(now);
        lsm(now)=rsm(now)=max(val(now),0);
    }
}
void pushdown(int now)
{
    if(rtg(now))
    {
        if(ls(now))
        {
            swap(ls(ls(now)),rs(ls(now)));
            swap(lsm(ls(now)),rsm(ls(now)));
            rtg(ls(now))^=1;
        }
        if(rs(now))
        {
            swap(ls(rs(now)),rs(rs(now)));
            swap(lsm(rs(now)),rsm(rs(now)));
            rtg(rs(now))^=1;
        }
    }
    if(ctg(now)!=INT_MAX)
    {
        if(ls(now))
        {
            sum(ls(now))=sz(ls(now))*ctg(now);
            val(ls(now))=ctg(now);
            lsm(ls(now))=rsm(ls(now))=max(sum(ls(now)),0);
            sub(ls(now))=max(val(ls(now)),sum(ls(now)));
            ctg(ls(now))=ctg(now);
        }
        if(rs(now))
        {
            sum(rs(now))=sz(rs(now))*ctg(now);
            val(rs(now))=ctg(now);
            lsm(rs(now))=rsm(rs(now))=max(sum(rs(now)),0);
            sub(rs(now))=max(val(rs(now)),sum(rs(now)));
            ctg(rs(now))=ctg(now);
        }
    }
    rtg(now)=false,ctg(now)=INT_MAX;
}
int merge(int x,int y)
{
    if(x) pushdown(x);
    if(y) pushdown(y);
    if(!x||!y) return x+y;
    if(rnd(x)<rnd(y))
    {
        rs(x)=merge(rs(x),y);
        update(x);
        return x;
    }
    else
    {
        ls(y)=merge(x,ls(y));
        update(y);
        return y;
    }
}
void split(int now,int k,int &x,int &y)
{
    if(!now) x=y=0;
    else
    {
        pushdown(now);
        if(sz(ls(now))>=k)
        {
            y=now;
            split(ls(y),k,x,ls(y));
        }
        else
        {
            x=now;
            split(rs(x),k-sz(ls(now))-1,rs(x),y);
        }
        update(now);
    }
}
void recycle(int now)
{
    if(!H[now]) dustbin.push(now),H[now]=false;
    if(ls(now)) recycle(ls(now));
    if(rs(now)) recycle(rs(now));
}
int build(int now)
{
    stack<int>S;
    int last;
    for(int i=1;i<=now;i++)
    {
        int x=new_node(a[i]);last=0;
        while(!S.empty()&&rnd(S.top())>rnd(x)) last=S.top(),update(S.top()),S.pop();
        if(!S.empty()) rs(S.top())=x;
        ls(x)=last,S.push(x);
    }
    while(!S.empty()) last=S.top(),update(S.top()),S.pop();
    return last;
}
int main()
{
    srand(19260817);
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i]=read();
    rt=build(n);
    while(m--)
    {
        char opt[20];
        scanf("%s",opt);
        if(opt[0]=='I')
        {
            int x,y,p,t;
            p=read(),t=read();
            split(rt,p,x,y);
            for(int i=1;i<=t;i++) a[i]=read();
            rt=merge(merge(x,build(t)),y);
        }
        else if(opt[0]=='D')
        {
            int x,y,z,p,t;
            p=read(),t=read();
            split(rt,p-1,x,y);
            split(y,t,y,z);
            recycle(y);
            rt=merge(x,z);
        }
        else if(opt[0]=='R')
        {
            int x,y,z,p,t;
            p=read(),t=read();
            split(rt,p-1,x,y);
            split(y,t,y,z);
            swap(ls(y),rs(y));
            swap(lsm(y),rsm(y));
            rtg(y)^=1;
            rt=merge(merge(x,y),z);
        }
        else if(opt[0]=='G')
        {
            int x,y,z,p,t;
            p=read(),t=read();
            split(rt,p-1,x,y);
            split(y,t,y,z);
            printf("%d\n",sum(y));
            rt=merge(merge(x,y),z);
        }
        else if(opt[0]=='M')
        {
            if(opt[2]=='K')
            {
                int x,y,z,p,t,tmp;
                p=read(),t=read(),tmp=read();
                split(rt,p-1,x,y);
                split(y,t,y,z);
                ctg(y)=val(y)=tmp,sum(y)=sz(y)*ctg(y);
                lsm(y)=rsm(y)=sub(y)=max(val(y),sum(y));
                rt=merge(merge(x,y),z);
            }
            else if(opt[2]=='X') printf("%d\n",sub(rt));
        }
    }
    return 0;
}
posted @ 2018-11-04 14:50  UranusITS  阅读(239)  评论(0编辑  收藏  举报