【 bzoj 1500 】NOI2005 维修序列 - 平衡树乱搞 treap

  嘛。。。又是屯了一年多的题。。。然而之前太弱了调不出来QAQ
  随便一个可以提取区间的平衡树都可以搞这道题。
  然而这题的splay我写过3个版本了。。。QAQ
  为了写WC2016的T3,用treap写了一发这题练练手。
  似乎没啥东西需要注意的。代码还好长,以后想办法缩一缩吧。。。
  

#include 
using namespace std;
#define rep(i,a,b) for (int i = a , _ = b ; i <= _ ; i ++)
#define per(i,a,b) for (int i = a , _ = b ; i >= _ ; i --)

#define maxn 500007

inline int rd() {
    char c = getchar();
    while (!isdigit(c) && c != '-') c = getchar() ; int x = 0 , f = 1;
    if (c == '-') f = -1; else x = c - '0';
    while (isdigit(c = getchar())) x = x * 10 + c - '0';
    return x * f;
}

inline int rnd() {
    static int rand_seed = 1542071823;
    rand_seed += rand_seed << 1 | 1;
    return rand_seed;
}

inline void upmax(int&a , int b) { if (a < b) a = b ; }

const int inf = 2000000000;

int n , m , a[maxn];

void input() {
    n = rd() , m = rd();
    rep (i , 1 , n) a[i] = rd();
}

#define fir first
#define sec second

static int DBG_CLOCK = 0;

namespace Treap {
    struct node;
    node *nil;
    struct node{
        node *l , *r;
        int key , pri , rv , cv , sz;
        int s , ls , rs , ms;

        node(int _key = 0): key(_key) , pri(rnd()) , l(nil) , r(nil) , rv(0) , cv(1001) , sz(1) { s = ls = rs = ms = key; }

        inline void upd() {
            sz = l->sz + r->sz + 1;
            s = l->s + r->s + key;

            ls = max(l->ls , l->s + key + max(0 , r->ls));
            rs = max(r->rs , r->s + key + max(0 , l->rs));

            ms = max(0 , l->rs) + key + max(0 , r->ls);
            assert(ms < inf);
            upmax(ms , max(l->ms , r->ms));
            assert(ms < inf);
        }

        inline void tag(int v) {
            if (this == nil) return;
            key = v , s = v * sz;
            ls = rs = ms = max(s , v);
            cv = v;
        }

        inline void rev() {
            if (this == nil) return;
            swap(l , r);
            swap(ls , rs);
            rv ^= 1;
        }

        inline void push() {
            if (this == nil) return;
            if (cv != 1001) {
                l -> tag(cv) , r -> tag(cv);
                cv = 1001;
            }
            if (rv) {
                l -> rev() , r -> rev();
                rv = 0;
            }
        }
    }data_pool[maxn] , *mem_pool[maxn] , *rt;
    int pool_top , data_top;

    typedef pair data;

    inline node *newnode(int key) {
        node *u;
        if (pool_top)
            u = mem_pool[pool_top --];
        else
            u = &data_pool[data_top ++];
        *u = node(key);
        return u;
    }

    inline void delnode(node *u) {
        mem_pool[++ pool_top] = u;
    }

    node *build(int *a , int n) {
        static node *stack[maxn] , *u , *pre;
        int top = 0;
        rep (i , 1 , n) {
            u = newnode(a[i]);
            pre = nil;
            while (top && stack[top]->pri > u->pri) {
                stack[top] -> upd();
                pre = stack[top];
                stack[top --] = nil;
            }
            if (top) stack[top] -> r = u;
            u -> l = pre;
            stack[++ top] = u;
        }
        while (top) stack[top --] -> upd();
        return stack[1];
    }

    node *join(node *u , node *v) {
        if (u == nil) return v;
        if (v == nil) return u;
        if (u->pri < v->pri) {
            u -> push();
            u -> r = join(u -> r , v);
            u -> upd();
            return u;
        } else {
            v -> push();
            v -> l = join(u , v -> l);
            v -> upd();
            return v;
        }
    }

    data split(node *u , int k) {
        if (u == nil) return data(nil , nil);
        data t;
        u -> push();
        if (u->l->sz >= k) {
            t = split(u -> l , k);
            u -> l = t.sec , t.sec = u;
        } else {
            t = split(u -> r , k - u->l->sz - 1);
            u -> r = t.fir , t.fir = u;
        }
        u -> upd();
        return t;
    }

    void remove(node *u) {
        if (u == nil) return;
        remove(u -> l) , remove(u -> r);
        delnode(u);
    }
}

using namespace Treap;

int pos , cnt;

inline void insert_() {
    rep (i , 1 , cnt) a[i] = rd();
    node *nr = build(a , cnt);
    data t = split(rt , pos);
    rt = join(join(t.fir , nr) , t.sec);
}

inline void delete_() {
    data t1 = split(rt , pos + cnt - 1) , t2 = split(t1.fir , pos - 1);
    remove(t2.sec);
    rt = join(t2.fir , t1.sec);
}

inline void reverse_() {
    data t1 = split(rt , pos + cnt - 1) , t2 = split(t1.fir , pos - 1);
    t2.sec -> rev();
    rt = join(join(t2.fir , t2.sec) , t1.sec);
}

inline void mk_same_() {
    int v = rd();
    data t1 = split(rt , pos + cnt - 1) , t2 = split(t1.fir , pos - 1);
    t2.sec -> tag(v);
    rt = join(join(t2.fir , t2.sec) , t1.sec);
}

inline void get_sum_() {
    data t1 = split(rt , pos + cnt - 1) , t2 = split(t1.fir , pos - 1);
    printf("%d\n" , t2.sec -> s);
    rt = join(join(t2.fir , t2.sec) , t1.sec);
}

inline void max_sum_() {
    printf("%d\n" , rt -> ms);
}

void solve() {
    nil = newnode(-inf);
    nil -> sz = nil -> s = 0;
    rt = build(a , n);
    char cmd[20];
    rep (i , 1 , m) {
        scanf("%s" , cmd);
        if (cmd[2] != 'X') pos = rd() , cnt = rd();
        switch (cmd[2]) {
            case 'S' : insert_ (); break ;
            case 'L' : delete_ (); break ;
            case 'V' : reverse_(); break ;
            case 'T' : get_sum_(); break ;
            case 'X' : max_sum_(); break ;
            case 'K' : mk_same_(); break ;
        }
    }
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("data.txt" , "r" , stdin);
    #endif
    input();
    solve();
    return 0;
}

你可能感兴趣的:(平衡树,treap,NOI)