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优越!

  • 相关阅读:
    手把手带你画一个 时尚仪表盘 Android 自定义View
    新手自定义view练习实例之(二) 波浪view
    新手自定义view练习实例之(一) 泡泡弹窗
    增加辅助的数据库组件
    解决Plugin is too old,please update to a more recent version,or set ANDROID_DAILY_OVERRIDE..
    Android 自定义View -- 简约的折线图
    android 开源图表库MPChart最简单使用方法示例教程Demo--折线图 柱状图
    改善database schema
    题解报告:hdu 2057 A + B Again
    hdu 2087 剪花布条(KMP入门)
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9362652.html
Copyright © 2011-2022 走看看