zoukankan      html  css  js  c++  java
  • BZOJ1251: 序列终结者

    【传送门:BZOJ1251


    简要题意:

      给出一个长度为n的序列,有m个操作,3种操作:

      1 l r k将l到r的数增加k

      2 l r将l到r的数列翻转

      3 l r求出l到r的最大值


    题解:

      裸SPLAY,直接下放两种标记,一种翻转,另一种增加值

      而且对于求l到r的区间,我们需要l-1和r+1的节点,而且不能用到0这个敏感位置,所以建树的时候,序列编号要从1到n+2


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct node
    {
        int son[2],f,mx,lazy,c,d;
        bool fz;
    }tr[51000];int root,len;
    void pushdown(int x)
    {
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(lc!=0) tr[lc].mx+=tr[x].lazy,tr[lc].d+=tr[x].lazy,tr[lc].lazy+=tr[x].lazy;
        if(rc!=0) tr[rc].mx+=tr[x].lazy,tr[rc].d+=tr[x].lazy,tr[rc].lazy+=tr[x].lazy;
        tr[x].lazy=0;
    }
    void reverse(int x)
    {
        tr[x].fz=false;
        swap(tr[x].son[0],tr[x].son[1]);
        int lc=tr[x].son[0],rc=tr[x].son[1];
        tr[lc].fz^=1;tr[rc].fz^=1;
    }
    void update(int x)
    {
        int lc=tr[x].son[0],rc=tr[x].son[1];
        tr[x].mx=tr[x].d;
        if(lc!=0) tr[x].mx=max(tr[x].mx,tr[lc].mx);
        if(rc!=0) tr[x].mx=max(tr[x].mx,tr[rc].mx);
        tr[x].c=tr[lc].c+tr[rc].c+1;
    }
    void rotate(int x,int w)
    {
        int f=tr[x].f,ff=tr[f].f;
        int r,R;
        r=tr[x].son[w];R=f;
        tr[R].son[1-w]=r;
        if(r!=0) tr[r].f=R;
        r=x;R=ff;
        if(tr[R].son[0]==f) tr[R].son[0]=r;
        else tr[R].son[1]=r;
        tr[r].f=R;
        r=f;R=x;
        tr[R].son[w]=r;
        tr[r].f=R;
        update(f);
        update(x);
    }
    int tmp[51000],s;
    void splay(int x,int rt)
    {
        int i=x;s=0;
        while(tr[i].f!=rt)
        {
            tmp[++s]=i;
            i=tr[i].f;
        }
        tmp[++s]=i;
        while(s!=0)
        {
            i=tmp[s--];
            if(tr[i].fz==true) reverse(i);
            if(tr[i].lazy!=0) pushdown(i);
        }
        while(tr[x].f!=rt)
        {
            int f=tr[x].f,ff=tr[f].f;
            if(ff==rt)
            {
                if(tr[f].son[0]==x) rotate(x,1);
                else rotate(x,0);
            }
            else
            {
                if(tr[f].son[0]==x&&tr[ff].son[0]==f){rotate(f,1);rotate(x,1);continue;}
                if(tr[f].son[1]==x&&tr[ff].son[0]==f){rotate(x,0);rotate(x,1);continue;}
                if(tr[f].son[0]==x&&tr[ff].son[1]==f){rotate(x,1);rotate(x,0);continue;}
                if(tr[f].son[1]==x&&tr[ff].son[1]==f){rotate(f,0);rotate(x,0);continue;}
            }
        }
        if(rt==0) root=x;
    }
    int bt(int l,int r)
    {
        if(l>r) return 0;
        int now=++len;
        tr[now].mx=tr[now].lazy=tr[now].d=0;
        tr[now].lazy=false;
        int mid=(l+r)/2;
        tr[now].son[0]=bt(l,mid-1);tr[now].son[1]=bt(mid+1,r);
        int lc=tr[now].son[0],rc=tr[now].son[1];
        if(lc!=0) tr[lc].f=now;
        if(rc!=0) tr[rc].f=now;
        tr[now].c=tr[lc].c+tr[rc].c+1;
        return now;
    }
    int finddizhi(int k)
    {
        int x=root;
        while(1)
        {
            if(tr[x].fz==true) reverse(x);
            if(tr[x].lazy!=0) pushdown(x);
            int lc=tr[x].son[0],rc=tr[x].son[1];
            if(k<=tr[lc].c) x=lc;
            else if(k>tr[lc].c+1){k-=tr[lc].c+1;x=rc;}
            else break;
        }
        return x;
    }
    void add(int l,int r,int k)
    {
        int lc=finddizhi(l-1),rc=finddizhi(r+1);
        splay(lc,0);splay(rc,lc);
        int x=tr[rc].son[0];
        tr[x].mx+=k;
        tr[x].d+=k;
        tr[x].lazy+=k;
        splay(x,0);
    }
    void fanzhuan(int l,int r)
    {
        int lc=finddizhi(l-1),rc=finddizhi(r+1);
        splay(lc,0);splay(rc,lc);
        int x=tr[rc].son[0];
        tr[x].fz^=1;
        splay(x,0);
    }
    void findmax(int l,int r)
    {
        int lc=finddizhi(l-1),rc=finddizhi(r+1);
        splay(lc,0);splay(rc,lc);
        int x=tr[rc].son[0];
        printf("%d
    ",tr[x].mx);
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        len=0;root=bt(1,n+2);
        for(int i=1;i<=m;i++)
        {
            int k,l,r,v;
            scanf("%d%d%d",&k,&l,&r);l++;r++;
            if(k==1)
            {
                int v;
                scanf("%d",&v);
                add(l,r,v);
            }
            if(k==2) fanzhuan(l,r);
            if(k==3) findmax(l,r);
        }
        return 0;
    }

     

  • 相关阅读:
    FTP服务总结
    编译安装hpptd2.4
    搭建DNS服务
    定制简单的Linux系统
    建立私有CA
    关于/boot文件的修复实验
    shell脚本进阶(二)
    datetime模块日期转换和列表sorted排序
    linux操作命令
    Python 中的特殊双下划线方法
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8933342.html
Copyright © 2011-2022 走看看