zoukankan      html  css  js  c++  java
  • [bzoj1500][NOI2005]维修数列_非旋转Treap

    维修数列 bzoj-1500 NOI-2005

    题目大意:给定n个数,m个操作,支持:在指定位置插入一段数;删除一个数;区间修改;区间翻转。查询:区间和;全局最大子序列。

    注释:$1le n_{max} le 5cdot 10^5$,$1le m le 2cdot 10^4$。

    想法:据说是... ...最GB的平衡树裸题,如果把这题切了,话说所有的平衡树都不怕了。

    具体的,

    插入和删除对于非旋转Treap来讲都是基本操作;

    区间修改的话我们就先删除然后插入即可;

    区间反转就打标记;

    区间和就是单点维护子树和;

    全局最大子序列的话像小白逛公园一样维护一下从左右开始的最长子序列。

    最后,附上丑陋的代码... ...

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define N 502333
    #define MAXN 4002333
    using namespace std;
    char c;int v;
    inline void read(int &x)
    {
        x=0;c=getchar();v=1;
        while(c<'0'||c>'9')
        {
            if(c=='-')v=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
        x*=v;
    }
    int n,m,root;
    struct Node
    {
        int ls,rs,size,key,val,sum,maxx,lmax,rmax,f;
        bool turn;
    }a[N];
    struct par{int x,y;};
    int q[MAXN],l=1,r,cnt,temp[N];
    inline void clear(int x)
    {
        a[x].ls=a[x].rs=a[x].size=a[x].key=a[x].val=0;
        a[x].maxx=a[x].lmax=a[x].rmax=a[x].turn=0;
        a[x].f=2333;
    }
    inline void update(int x)
    {
        int ls=a[x].ls,rs=a[x].rs;
        a[x].size=1;a[x].maxx=a[x].sum=a[x].val;
        if(ls)a[x].size+=a[ls].size,a[x].sum+=a[ls].sum,a[x].maxx=max(a[x].maxx,a[ls].maxx);
        if(rs)a[x].size+=a[rs].size,a[x].sum+=a[rs].sum,a[x].maxx=max(a[x].maxx,a[rs].maxx);
        a[x].maxx=max(a[x].maxx,a[ls].rmax+a[x].val+a[rs].lmax);
        a[x].lmax=max(a[ls].lmax,a[ls].sum+a[x].val+a[rs].lmax);
        a[x].rmax=max(a[rs].rmax,a[rs].sum+a[x].val+a[ls].rmax);
    }
    inline void pushdown(int x)
    {
        if(!x)return;
        int ls=a[x].ls,rs=a[x].rs;
        if(a[x].turn)
        {
            if(ls)
            {
                a[ls].turn^=1;
                swap(a[ls].lmax,a[ls].rmax);
            }
            if(rs)
            {
                a[rs].turn^=1;
                swap(a[rs].lmax,a[rs].rmax);
            }
            swap(a[x].ls,a[x].rs);
            a[x].turn=0;
        }
        ls=a[x].ls,rs=a[x].rs;
        if(a[x].f!=2333)
        {
            if(ls)
            {
                a[ls].f=a[ls].val=a[x].f;a[ls].sum=a[ls].size*a[ls].f;
                if(a[ls].f>0)a[ls].maxx=a[ls].lmax=a[ls].rmax=a[ls].sum;
                else a[ls].maxx=a[ls].f,a[ls].lmax=a[ls].rmax=0;
            }
            if(rs)
            {
                a[rs].f=a[rs].val=a[x].f;a[rs].sum=a[rs].size*a[rs].f;
                if(a[rs].f>0)a[rs].maxx=a[rs].lmax=a[rs].rmax=a[rs].sum;
                else a[rs].maxx=a[rs].f,a[rs].lmax=a[rs].rmax=0;
            }
            a[x].f=2333;
        }
    }
    int merge(int x,int y)
    {
        if(!x||!y)return x|y;
        pushdown(x),pushdown(y);
        if(a[x].key>a[y].key)
        {
            a[x].rs=merge(a[x].rs,y);update(x);
            return x;
        }
        a[y].ls=merge(x,a[y].ls);update(y);
        return y;
    }
    par split(int x,int k)
    {
        if(!k)return (par){0,x};
        pushdown(x);
        int ls=a[x].ls,rs=a[x].rs;
        if(k==a[ls].size)
        {
            a[x].ls=0;update(x);
            return (par){ls,x};
        }
        if(k==a[ls].size+1)
        {
            a[x].rs=0;update(x);
            return (par){x,rs};
        }
        if(k<a[ls].size)
        {
            par t=split(ls,k);
            a[x].ls=t.y;update(x);
            return (par){t.x,x};
        }
        par t=split(rs,k-a[ls].size-1);
        a[x].rs=t.x;update(x);
        return (par){x,t.y};
    }
    inline int makenew(int x)
    {
        int p;
        if(l<=r)p=q[l++];
        else p=++cnt;
        a[p].size=1,a[p].maxx=a[p].sum=a[p].val=x;
        a[p].lmax=a[p].rmax=max(x,0);
        a[p].turn=0,a[p].f=2333;
        a[p].key=rand();
        return p;
    }
    int build(int L,int R)
    {
        if(L==R)return makenew(temp[L]);
        int mid=(L+R)>>1;
        return merge(build(L,mid),build(mid+1,R));
    }
    void del(int x)
    {
        if(!x)return;
        del(a[x].ls);
        del(a[x].rs);
        clear(x);
        q[++r]=x;
    }
    int main()
    {
        read(n),read(m);
        for(int i=1;i<=n;i++)read(temp[i]);
        root=build(1,n);
        char flag[10];
        for(int x,num,val,j,i=1;i<=m;i++)
        {
            scanf("%s",flag);
            if(flag[0]=='I')
            {
                read(x);read(num);
                for(j=1;j<=num;j++)read(temp[j]);
                par t=split(root,x);
                root=merge(merge(t.x,build(1,num)),t.y);
            }
            else if(flag[0]=='D')
            {
                read(x);read(num);x--;
                par t1=split(root,x),t2=split(t1.y,num);
                del(t2.x);
                root=merge(t1.x,t2.y);
            }
            else if(flag[0]=='R')
            {
                read(x);read(num);x--;
                par t1=split(root,x),t2=split(t1.y,num);
                a[t2.x].turn^=1;swap(a[t2.x].lmax,a[t2.x].rmax);
                root=merge(t1.x,merge(t2.x,t2.y));
            }
            else if(flag[0]=='G')
            {
                read(x);read(num);x--;
                par t1=split(root,x),t2=split(t1.y,num);
                printf("%d
    ",a[t2.x].sum);
                root=merge(t1.x,merge(t2.x,t2.y));
            }
            else if(flag[2]=='X')printf("%d
    ",a[root].maxx);
            else 
            {
                read(x);read(num);read(val);x--;
                par t1=split(root,x),t2=split(t1.y,num);
                a[t2.x].f=a[t2.x].val=val;a[t2.x].sum=val*a[t2.x].size;
                if(val>0)a[t2.x].maxx=a[t2.x].lmax=a[t2.x].rmax=a[t2.x].sum;
                else a[t2.x].maxx=val,a[t2.x].lmax=a[t2.x].rmax=0;
                root=merge(t1.x,merge(t2.x,t2.y));
            }
        }
        return 0;
    }
    

    小结:裸题就是开心... ...

    P.S.:非旋转Treap就是比splay优越!

  • 相关阅读:
    Java实现 LeetCode 56 合并区间
    JQuery实现对html结点的操作(创建,添加,删除)
    JQuery实现对html结点的操作(创建,添加,删除)
    JQuery实现对html结点的操作(创建,添加,删除)
    Java实现 LeetCode 55 跳跃游戏
    Java实现 LeetCode 55 跳跃游戏
    Java实现 LeetCode 55 跳跃游戏
    Java实现 LeetCode 54 螺旋矩阵
    Java实现 LeetCode 54 螺旋矩阵
    Java实现 LeetCode 54 螺旋矩阵
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9362652.html
Copyright © 2011-2022 走看看