zoukankan      html  css  js  c++  java
  • BZOJ 1500 [NOI2005]维修数列 题解

    这道题还是比较裸的, 就是有点难码, 感觉能错的地方都错了一遍... 这里就提一些注意事项吧:

    感觉对Splay一些基本操作的理解不够,或者说,对于线段树的一些基本操作理解不够.在维护下传标记方面Splay和线段树是相通的.这是一些问题:

    • 标记在什么时候下传:更具定义,在需要往下走的时候下传,即寻找第k大的时候.其他时候…其实是没有必要的.
    • 修改标记的定义:和线段树一样,一个点的标记定义为它的子树应该要更改的部分,所以在修改一个值的同时,不仅要修改它的标记,还要将它本身的值修改.这东西最好写一个函数,至少在这道题写函数之后才对的,并且并不知道bug处在哪
    • Splay前的更新:即在Splay之前将根节点到这个点上的所有点都pushdown.虽然有些代码没有写,但感觉还是要写一写为好.不写可能会错?
    • 前缀,后缀最大值的包含与不包含的问题:考虑它能不能不选.例如这道题,不能不选,所以如果全是负数,最大值也不能是0.
    • 前,后哨兵问题:哨兵是肯定要有的,否则肯定会出bug.对于哨兵的值的问题…这种维护数列的问题一般是设成0吧…这样的话就不会影响原来的值了.如果会影响的话,那么对于输出值的问题就可以将整个区间split出来就好了.

    这里贴上调了若干天的代码 >_< :

    #include <bits/stdc++.h>
    #define lc(x) ch[(x)][0]
    #define rc(x) ch[(x)][1]
    #define INF 0x3f3f3f3f
    #define N 1000006
    using namespace std;
    
    inline void cmax(int& x, int y) {
        if (x < y) x = y;
    }
    
    inline int read() { int x; scanf("%d", &x); return x;}
    
    int cnt = 0, root, fa[N], ch[N][2], val[N], sz[N], rpl[N], rev[N], sum[N], lft[N], rht[N], mxs[N];
    int stk[N], top;
    
    inline void update(int x) {
        sz[x] = sz[lc(x)] + sz[rc(x)] + 1;
        sum[x] = sum[lc(x)] + sum[rc(x)] + val[x];
        lft[x] = sum[lc(x)] + val[x];
        if (rc(x)) cmax(lft[x], lft[x] + lft[rc(x)]);
        if (lc(x)) cmax(lft[x], lft[lc(x)]);
        rht[x] = sum[rc(x)] + val[x];
        if (lc(x)) cmax(rht[x], rht[x] + rht[lc(x)]);
        if (rc(x)) cmax(rht[x], rht[rc(x)]);
        mxs[x] = max(0, rht[lc(x)]) + val[x] + max(0, lft[rc(x)]);
        if (lc(x)) cmax(mxs[x], mxs[lc(x)]);
        if (rc(x)) cmax(mxs[x], mxs[rc(x)]);
    }
    
    inline void rever(int x) {
        swap(lc(x), rc(x));
        swap(lft[x], rht[x]);
        rev[x] ^= 1;
    }
    
    inline void tagup(int x, int w) {
        rpl[x] = val[x] = w;
        sum[x] = lft[x] = rht[x] = mxs[x] = sz[x] * w;
        if (w < 0) lft[x] = rht[x] = mxs[x] = w;
    }
    
    inline void pushdown(int x) {
        if (rev[x]) {
            if (lc(x)) rever(lc(x));
            if (rc(x)) rever(rc(x));
            rev[x] = 0;
        }
        if (rpl[x] != INF) {
            if (lc(x)) tagup(lc(x), rpl[x]);
            if (rc(x)) tagup(rc(x), rpl[x]);
            rpl[x] = INF;
        }
    }
    
    void pushup(int x) {
        if (fa[x]) pushup(fa[x]);
        pushdown(x);
    }
    
    inline void rotate(int x) {
        int y = fa[x], z = fa[y], d = rc(y) == x;
        pushdown(y), pushdown(x);
        ch[y][d] = ch[x][!d], fa[ch[y][d]] = y;
        fa[y] = x, ch[x][!d] = y; fa[x] = z;
        if (z) ch[z][rc(z) == y] = x;
        update(y), update(x);
    }
    
    inline void splay(int x, int goal) {
        pushup(x);
        while (fa[x] != goal) {
            int y = fa[x], z = fa[y];
            if (z != goal) rotate((rc(y) == x) == (rc(z) == y) ? y : x);
            rotate(x);
        }
        if (!goal) root = x;
    }
    
    inline int Get() {
        return top ? stk[top--] : ++cnt;
    }
    
    int kth(int k) {
        int rt = root;
        while (rt) {
            pushdown(rt);
            if (sz[lc(rt)] >= k) rt = lc(rt);
            else if (sz[lc(rt)] + 1 == k) return rt;
            else k -= sz[lc(rt)] + 1, rt = rc(rt);
        }
    }
    
    inline void isrt() {
        int k = read(), tot = read();
        splay(kth(k + 2), 0), splay(kth(k + 1), root);
        int lst = lc(root);
        rc(lst) = Get();
        while (tot--) {
            fa[rc(lst)] = lst;
            lst = rc(lst);
            val[lst] = read();
            if (tot) rc(lst) = Get();
        }
        splay(lst, 0);
    }
    
    void recy(int rt) {
        if (lc(rt)) recy(lc(rt));
        if (rc(rt)) recy(rc(rt));
        sum[rt] = val[rt] = sz[rt] = lc(rt) = rc(rt) = fa[rt] = 0;
        rpl[rt] = INF, rev[rt] = lft[rt] = rht[rt] = mxs[rt] = 0;
        stk[++top] = rt;
    }
    
    void output(int x) {
        pushdown(x);
        if (lc(x)) output(lc(x));
        if (rc(x)) output(rc(x));
        update(x);
    }
    
    
    inline void dele() {
        int k = read(), tot = read(), x;
        splay(kth(k + tot + 1), 0), splay(kth(k), root);
        x = rc(lc(root));
        recy(x); rc(lc(root)) = 0;
        splay(lc(root), 0);
    }
    
    inline void mdfy() {
        int k = read(), tot = read(), c = read(), x;
        splay(kth(k + tot + 1), 0), splay(kth(k), root);
        x = rc(lc(root));
        tagup(x, c);
        splay(x, 0);
    }
    
    inline void reve() {
        int k = read(), tot = read(), x, y = kth(k), z = kth(k + tot + 1);
        splay(z, 0), splay(y, root);
        x = rc(lc(root));
        rever(x);
        splay(x, 0);
    }
    
    inline int gtsum() {
        int k = read(), tot = read(), x, y = kth(k), z = kth(k + tot + 1);
        splay(z, 0), splay(y, root);
        x = rc(lc(root));
        return sum[x];
    }
    
    void getupdate(int x) {
        pushdown(x);
        if (lc(x)) getupdate(lc(x));
        if (rc(x)) getupdate(rc(x));
        update(x);
    }
    
    inline int mxsum() {
        splay(1, 0), splay(kth(sz[root]), 1);
        return mxs[lc(rc(root))];
    }
    
    int main() {
        memset(rpl, 0x3f, sizeof rpl);
        int n, m;
        n = read(), m = read();
        root = 1;
        rc(1) = 2;
        for (int i = 2; i <= n + 1; ++i) {
            val[i] = read();
            fa[i] = i - 1;
            rc(i) = i + 1;
            update(i);
        }
        fa[cnt = n + 2] = n + 1;
        splay(n + 2, root);
        getupdate(root);
        char op[20];
        while (m--) {
            scanf("%s", op);
            if (*op == 'I') isrt();
            if (*op == 'D') dele();
            if (*op == 'M' && *(op + 2) == 'K') mdfy();
            if (*op == 'R') reve();
            if (*op == 'G') printf("%d
    ", gtsum());
            if (*op == 'M' && *(op + 2) == 'X') printf("%d
    ", mxsum());
        }
        return 0;
    }
    
    
  • 相关阅读:
    [UE4]Image
    [UE4]CheckBox
    [UE4]Button
    [UE4]Border
    [UE4]RichTextBlock
    [UE4]Text Box
    [UE4]字体材质
    [UE4]Retainer Box
    [UE4]Invalidation Box
    [UE4]Dynamic Entry Box
  • 原文地址:https://www.cnblogs.com/hnfms-jerry/p/solution_bzoj1500.html
Copyright © 2011-2022 走看看