【BZOJ 1251】序列终结者 splay模板

16 篇文章 0 订阅
7 篇文章 0 订阅

模板:区间反转,区间加某一个值,区间求最大值

坑点:首尾各加上两个节点后,注意第一个新加点的初值。

这个东西应该叫名次树吧,写完这个东西最大的体会就是,树上每个节点的标号其实就是人们思维上那个点应该出现的value的索引值,怎么标并不重要。

#include<bits/stdc++.h>
typedef long long LL;
typedef int lint;
using namespace std;
const LL maxn = 100000+10;
const LL inf= 0x7fffffff;
LL a[maxn];
struct Splay{
    lint fa[maxn],sz[maxn],ch[maxn][2],root,flag[maxn];
    LL val[maxn],laz[maxn],Max[maxn];
    void init(  ){
        memset( fa,0,sizeof( fa ) );
        memset( ch,0,sizeof( ch ) );
        memset( sz,0,sizeof(sz ) );
        memset( laz,0,sizeof( laz ) );
        memset( flag,0,sizeof( flag ) );
    }
    lint get( lint x ){
        return x == ch[ fa[x] ][1];
    }
    void push_up( lint x ){
        sz[x] = sz[
        ch[x][0] ] + sz[ ch[x][1] ] + 1;
        Max[x] = max(max( Max[ ch[x][0] ],Max[ ch[x][1] ] ) ,val[ x ]);
    }
    void push_down1( lint x ){
        lint lc = ch[x][0];
        lint rc = ch[x][1];
        if( lc ){
            flag[ lc ] ^= 1;
            swap( ch[lc][0],ch[lc][1] );
        }
        if( rc ){
            flag[ rc ] ^= 1;
            swap( ch[rc][0],ch[rc][1]  );
        }
        flag[x] = 0;
    }
    void push_down2( lint x ){
        lint lc = ch[x][0];
        lint rc = ch[x][1];
        if( lc ){
            laz[lc] += laz[x];
            val[lc] += laz[x];
            Max[lc] += laz[x];
        }
        if( rc ){
            laz[rc] += laz[x];
            val[rc] += laz[x];
            Max[rc] += laz[x];
        }
        laz[x] = 0;
    }
    void Rotate( lint x ){
        lint f = fa[x],ff = fa[f],d = get(x);
        if(ff)ch[ff][ get(f) ] = x; fa[x] = ff;
        if( ch[x][!d] )fa[ch[x][!d]] = f;ch[f][d] = ch[x][!d];
        fa[f] = x; ch[x][!d] = f;
        push_up( f );
        push_up( x );
    }
    lint Find( lint x,lint k ){
        if( flag[x] ) push_down1(x);
        if( laz[x] ) push_down2(x);
        lint lc = ch[x][0],rc = ch[x][1];
        if( k ==sz[ lc ] + 1 ){
            return x;
        }else if( k <= sz[lc] ){
            return Find( lc,k );
        }else{
            return Find( rc,k - sz[lc]-1 );
        }
    }
    void splay( lint x,lint y = 0 ){
        lint p = x;
        vector<lint> ve;
        while( p && p != y ) { ve.push_back( p ); p = fa[p];}
        for( lint i = ve.size()-1;i >= 0;i-- ){
            if( flag[ ve[i] ] )push_down1( ve[i] );
            if( laz[ ve[i] ] ) push_down2( ve[i] );
        }
        while(fa[x] != y ){
            if( fa[ fa[x] ] == y ){
                Rotate(x);
            }else{
                if( get( x ) == get( fa[x] ) ) Rotate( fa[x] );
                else Rotate( x );
                Rotate( x );
            }
        }
        if(!y)root = x;
    }
    void Reverse( lint x,lint y ){
        lint u = Find( root,x-1 );
        lint v = Find( root,y+1 );
        splay( u );
        splay( v,u );
        lint lc = ch[v][0];
        flag[ lc ] ^= 1LL;
        swap( ch[lc][0],ch[lc][1] );
    }
    void change( LL l,LL r,LL v ){
        lint x = Find( root,l-1 );
        lint y = Find( root,r+1 );
        splay( x );
        splay( y,x );
        lint lc = ch[y][0];
        laz[ lc ] += v;
        val[ lc ] += v;
        Max[lc] += v;
    }
    lint build( lint l,lint r ){
        if( l > r ) return 0;
        lint mid = l + r >> 1;
        val[mid] = a[mid];
        Max[mid] = val[mid];
        ch[mid][0] = build( l,mid-1 ); if( ch[mid][0] )fa[ ch[mid][0] ] = mid;
        ch[mid][1] = build( mid+1,r ); if( ch[mid][1] )fa[ ch[mid][1] ] = mid;
        push_up( mid );
        return mid;
    }
   /* void dfs( LL x ){
        if(flag[x]) push_down(x);
        if( ch[x][0] ) dfs( ch[x][0] );
        if( x != 1 && x != n+2 )
        printf("%lld ",val[x]);
        if( ch[x][1] ) dfs( ch[x][1] );
    }*/
    LL ask( lint l,lint r ){
        lint x = Find(root,l-1);
        lint y = Find( root,r+1 );
        splay(x);
        splay( y,x );
        lint lc = ch[y][0];
        return Max[lc];
    }
}g;
int main(){

   lint n,m,q,x,y,v;
   scanf("%d%d",&n,&m);
   n += 2;
   for( lint i = 1;i <= n;i++ ) a[i] = 0;
   a[1] = -inf; a[n] = -inf;
   g.Max[0] = g.val[0] = -inf;
    //g.init();
    g.root = g.build(1,n);
    for( lint i = 1;i <= m;i++ ){
        scanf("%d",&q);
        if( q == 1 ){
            scanf("%d%d%d",&x,&y,&v);
            x++;y++;
            g.change(x,y,v);
        }else if( q == 2 ){
            scanf("%d%d",&x,&y);
            x++;y++;
            g.Reverse(x,y);
        }else{
            scanf("%d%d",&x,&y);
            x++; y++;
            LL ans = g.ask( x,y );
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值