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

    Description

    BZOJ1251
    Luogu4146
    维护一个序列,支持区间加,区间翻转,区间取最大值这三个操作。

    Solution

    Splay.
    就是细节比较麻烦。

    Code

    #include <cstdio>
    #include <algorithm>
     
    const int N = 50000 + 10;
     
    int fa[N], ch[N][2], val[N], sz[N], rev[N], add[N], mx[N];
     
    void upd(int x) {
        sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1;
        mx[x] = std::max(val[x], std::max(mx[ch[x][0]], mx[ch[x][1]]));
    }
    void pd(int x) {
        if (rev[x]) {
            std::swap(ch[x][0], ch[x][1]);
            rev[ch[x][0]] ^= 1;
            rev[ch[x][1]] ^= 1;
            rev[x] = 0;
        }
        if (add[x]) {
            if (ch[x][0]) val[ch[x][0]] += add[x], add[ch[x][0]] += add[x], mx[ch[x][0]] += add[x];
            if (ch[x][1]) val[ch[x][1]] += add[x], add[ch[x][1]] += add[x], mx[ch[x][1]] += add[x];
            add[x] = 0;
        }
    }
    int dir(int x) { return x == ch[fa[x]][1]; }
    void rot(int x) {
        int f = fa[x], d = dir(x);
        if (fa[x] = fa[f]) ch[fa[x]][dir(f)] = x;
        if (ch[f][d] = ch[x][d^1]) fa[ch[f][d]] = f;
        ch[fa[f] = x][d^1] = f;
        upd(f);
        upd(x);
    }
    int st[N];
    void splay(int x, int t = 0) {
        int top = 0, i;
        for (i = x; fa[i]; i = fa[i]) st[top++] = fa[i];
        while (top--) pd(st[top]);
        pd(x);
        for (; fa[x] != t; rot(x)) if (fa[fa[x]] != t) rot(dir(fa[x]) == dir(x) ? fa[x] : x);
    }
    int kth(int k, int t) {
        int o = t; 
        while (1) {
            pd(o);
            if (sz[ch[o][0]] == k-1) break;
            else if (sz[ch[o][0]] >= k) o = ch[o][0];
            else { k -= sz[ch[o][0]] + 1; o = ch[o][1]; }
        }
        splay(o, fa[t]);
        return o;
    }
    int n;
    void reverse(int l, int r) {
        splay(1);
        int y = kth(r+1, 1);
        int x = ch[y][0];
        kth(l-1, x);
        rev[ch[ch[y][0]][1]] ^= 1;
    }
    void addval(int l, int r, int k) {
        splay(1);
         
        int y = kth(r+1, 1);
        int x = ch[y][0];
        kth(l-1, x); 
        add[ch[ch[y][0]][1]] += k;
        val[ch[ch[y][0]][1]] += k;
        mx[ch[ch[y][0]][1]] += k;
    }
    int query(int l, int r) {
        splay(1);
        int y = kth(r+1, 1);
        int x = ch[y][0];
        kth(l-1, x);
        return mx[ch[ch[y][0]][1]];
    }
     
    void put(int o) {
        if (!o) return;
        put(ch[o][0]);
        printf("%d %d %d
    ", ch[o][0], ch[o][1], val[o]);
        put(ch[o][1]); 
    }
     
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n+2; ++i) {
            if (fa[i] = i-1) ch[i-1][1] = i;
            sz[i] = n - i + 3;
            val[i] = 0;
        }
        mx[0] = -2147483647;
        val[n+1] = 0;
        int m, l, r, v, op;
        scanf("%d", &m);
        while (m--) {
            scanf("%d%d%d", &op, &l, &r);
            if (op == 1) { scanf("%d", &v); addval(l+1, r+1, v); }
            else if (op == 2) reverse(l+1, r+1);
            else printf("%d
    ", query(l+1, r+1));
        }
        return 0;
    }
    

    Note

    如果不是非常必要的话,还是不要使用平衡树了,实在是有点难调,也没有线段树直观。

  • 相关阅读:
    inet_ntoa解析
    日语常用计算机词汇
    Visual Studio 2012 : error LNK2026: module unsafe for SAFESEH image
    android异常总结四 :Unexpected text found in layout file: """
    android异常总结三 :R文件丢失
    android异常总结二 :This text field does not specify an inputType or a hint
    android异常总结一 :reslayoutOtherActivity.xml: Invalid file name: must contain only [a-z0-9_.]
    Win8下配置java环境
    CUDA实例练习(五):两数相加
    CUDA实例练习(四):矩阵转置
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/bzoj1251.html
Copyright © 2011-2022 走看看