[BZOJ1251]序列终结者

序列终结者

Description
网上有许多题,就是给定一个序列,要你支持几种操作:A、B、C、D。一看另一道题,又是一个序列 要支持几种操作:D、C、B、A。尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思。这道题目 就叫序列终结者吧。 【问题描述】 给定一个长度为N的序列,每个序列的元素是一个整数(废话)。要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V。 2. 将[L,R]这个区间翻转,比如1 2 3 4变成4 3 2 1。 3. 求[L,R]这个区间中的最大值。 最开始所有元素都是0。
Input
第一行两个整数N,M。M为操作个数。 以下M行,每行最多四个整数,依次为K,L,R,V。K表示是第几种操作,如果不是第1种操作则K后面只有两个数。
Output
对于每个第3种操作,给出正确的回答。
Sample Input
4 4
1 1 3 2
1 2 4 -1
2 1 3
3 2 4
Sample Output
2
【数据范围】
N<=50000,M<=100000。

Solution
一些基本的区间操作,这里不用splay而用fhq treap来实现,实际5200ms,而且建treap都没有用上线性的笛卡尔树建树方法,这样相比之下hzwer的splay要8000+ms,效果还是比较明显的

Code

#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define per(i, r, l) for (int i = (r); i >= (l); i--)
#define X first
#define Y second
#define MS(_) memset(_, 0, sizeof(_))
#define PB push_back
#define MP make_pair
#define CLEAR\
    root = merge(A.X, merge(B.X, B.Y));
#define debug(...) fprintf(stderr, __VA_ARGS__)

template<typename T> inline void read(T &x){
    x = 0; T f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch))  {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
}

const int INF = 2147483647;
struct Treap{
    Treap *lc, *rc;
    int fix, size, val, delta, mx, tag; 
    Treap(int _val):fix(rand()), size(1), val(_val), lc(NULL), rc(NULL), tag(false), delta(0), mx(0) {}
    inline void add(int d){ mx += d; val += d; delta += d; }
    inline void rev() { tag ^= 1; }
    inline void sink(){
        if (delta){
            if (lc) lc->add(delta); if (rc) rc->add(delta);
            delta = 0;
        }
        if (tag){
            if (lc) lc->rev(); if (rc) rc->rev();
            swap(lc, rc); tag ^= 1;
        }
    }
    inline void update(){
        size = 1 + (lc ? lc->size : 0) + (rc ? rc->size : 0);
        mx = max(val, max(lc ? lc->mx : -INF, rc ? rc->mx : -INF));
    }
}*root;
typedef pair<Treap*, Treap*> droot;
int n, m;

inline int sz(Treap *x) {return x ? x->size : 0;}
Treap *merge(Treap *A, Treap *B){
    if (!A) return B;
    if (!B) return A;
    A->sink(); B->sink();
    if (A->fix < B->fix){
        A->rc = merge(A->rc, B); A->update();
        return A;
    }else{
        B->lc = merge(A, B->lc); B->update();
        return B;
    }
}
droot split(Treap *A, int k){ droot ans;
    if (!A) return droot(NULL, NULL);
    A->sink();
    if (sz(A->lc) >= k){
        ans = split(A->lc, k);
        A->lc = ans.Y; A->update();
        ans.Y = A;
    }else{
        ans = split(A->rc, k-sz(A->lc)-1);
        A->rc = ans.X; A->update();
        ans.X = A;  
    }
    return ans;
}
inline void insert(int k, int value){
    Treap *tmp; 
    droot y = split(root, k-1); 
    tmp = new Treap(value);
    root = merge(merge(y.X, tmp), y.second);
}
int main(){
    read(n); read(m);
    rep(i, 1, n) insert(i, 0);

    rep(i, 1, m){ int opt, l, r, v; droot A, B;
        read(opt); read(l); read(r);
        A = split(root, l-1); B = split(A.Y, r-l+1);
        if (opt == 1){ read(v); B.X->add(v); CLEAR }
        else if (opt == 2){ B.X->rev(); CLEAR }
        else { printf("%d\n", B.X->mx); CLEAR }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值