【NOI 2005】 维修数列

【题目链接】

           点击打开链接

【算法】

           本题所运用的也是Splay的区间操作,但是实现较为困难

            INSERT操作

            将pos splay至根节点,pos+1 splay至根节点的右节点,然后对根节点的右节点的左节点建树即可

            DELETE操作

            将l-1 splay至根节点, r+1 splay至根节点的右节点,直接“砍断”根节点的右节点的左节点

            MAKE_SAME操作

            将l-1 splay至根节点,r+1 splay至根节点的右节点,给根节点的右节点的左节点打上标记

            REVERSE操作

            将l-1 splay至根节点,r+1 splay至根节点的右节点,给根节点的右节点的左节点打上标记

            GET_SUM操作

            将l-1 splay至根节点,r+1 splay至根节点的右节点,直接输出根节点的右节点的左节点的sum

            MAX_SUM操作

            此操作的实现类似于树形DP :

            我们不妨给每个节点增加三个域

            lmax :从这个节点所代表的区间的左端点开始向右延伸的最大和

            rmax :从这个节点所代表的区间的右端点开始像左延伸的最大和

            max : 该节点所代表区间的最大连续子段和

            那么,lmax该如何取值?

            令根节点为root,根节点的左儿子为lc,根节点的右儿子为rc

            我们可以分情况讨论 :

            若lmax[root]不包括root,lmax[root] = lmax[lc]

            lmax[root]包括root,那么 : 若不向右继续延伸,则lmax[root] = tot[lc] + val[root],若向右延伸,

            则lmax[root] = tot[lc] + val[root] + lmax[rc]

            我们只要在这三者中取最大值就可以了

            rmax同理

            那么,max又该如何取值呢?

            我们还是分情况讨论 :

            令根节点为root,根节点的左儿子为rc,根节点的右儿子为rc

            若max[root]不包括root,max[root] = max{max[lc],max[rc]}

            max[root]包括root,那么 : 若不向右也不向左延伸,则max[root] = val[root],若向左延伸,

            则max[root] = val[root] + rmax[lc]

            若向右延伸,则 :

             max[root] = val[root] + lmax[rc]

            若两边同时延伸,则 :

            max[root] = val[root] + rmax[rc] + lmax[lc]

            只需在这五者中取最大值即可

            关于内存池 :

            由于本题数据量较大,我们要进行内存回收,内存回收方法如下 :

            我们建立一个内存池,开始时将所有可用空间都放入内存池,插入一个节点时,我们从内存池弹出一个节点,

            分配给这个节点,删除时,我们将要删除的节点放回内存池,如果是删除一棵子树,则将整棵子树放回内存池

            这个内存池可以用栈,队列,链表等许多数据结构来维护,笔者选用的是栈,由于维护方法比较简单,笔者不再赘述

【代码】

          本题的细节很多,写代码时一定要严谨!

         

#include<bits/stdc++.h>
using namespace std;
#define MAXN 20000
#define MAXX 500000
const int INF = 2e9;

int i,N,M,tot,pos,val;
int a[MAXX+10];
char opt[10];
stack<int> stk;

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

template <typename T> inline void write(T x) {
    if (x < 0) { putchar('-'); x = -x; }
    if (x > 9) write(x/10);
    putchar(x%10+'0');
}

template <typename T> inline void writeln(T x) {
    write(x);
    puts("");
}

struct Splay {
        int root;
        struct Node {
                int fa,son[2],size,lmax,rmax,tot,
                        Max,val,lazy;
                bool rev;
        } Tree[MAXX+10];
        inline bool get(int x) {
                return Tree[Tree[x].fa].son[1] == x;
        }
        inline void build(int index,int l,int r) {
                int id,mid;
                mid = (l + r) >> 1;
                Tree[index].lazy = INF;
                Tree[index].rev = 0;
                Tree[index].val = a[mid];
                if (l == r) {
                        Tree[index].size = 1;
                        Tree[index].lmax = Tree[index].rmax = Tree[index].Max = Tree[index].tot = a[mid];
                        return;
                }
                if (l < mid) {
                        id = stk.top();
                        stk.pop();
                        Tree[index].son[0] = id;
                        Tree[id].fa = index;
                        build(id,l,mid-1);
                }
                if (mid < r) {
                        id = stk.top();
                        stk.pop();
                        Tree[index].son[1] = id;
                        Tree[id].fa = index;
                        build(id,mid+1,r);
                }
                update(index);
        }
        inline void update(int index) {
                if (!index) return;
                Tree[index].tot = Tree[Tree[index].son[0]].tot + Tree[Tree[index].son[1]].tot + Tree[index].val;
                Tree[index].size = Tree[Tree[index].son[0]].size + Tree[Tree[index].son[1]].size + 1;
                Tree[index].lmax = max(Tree[Tree[index].son[0]].lmax,Tree[Tree[index].son[0]].tot+max(Tree[Tree[index].son[1]].lmax,0)+Tree[index].val);
                Tree[index].rmax = max(Tree[Tree[index].son[1]].rmax,Tree[Tree[index].son[1]].tot+max(Tree[Tree[index].son[0]].rmax,0)+Tree[index].val);
                Tree[index].Max = max(Tree[Tree[index].son[0]].Max,max(Tree[Tree[index].son[1]].Max,Tree[index].val+max(Tree[Tree[index].son[0]].rmax,0)+max(Tree[Tree[index].son[1]].lmax,0)));
        }
        inline void pushdown(int index) {
                int tmp;
                if (Tree[index].lazy != INF) {
                        tmp = Tree[index].lazy;
                        Tree[index].lazy = INF;
                        if (Tree[index].son[0]) Tree[Tree[index].son[0]].tot = Tree[Tree[index].son[0]].size * tmp;
                        if (Tree[index].son[1]) Tree[Tree[index].son[1]].tot = Tree[Tree[index].son[1]].size * tmp;
                        if (Tree[index].son[0]) Tree[Tree[index].son[0]].val = tmp;
                        if (Tree[index].son[1]) Tree[Tree[index].son[1]].val = tmp;    
                        if (Tree[index].son[0]) Tree[Tree[index].son[0]].lmax = Tree[Tree[index].son[0]].rmax = Tree[Tree[index].son[0]].Max = max(tmp,Tree[Tree[index].son[0]].size*tmp);
                        if (Tree[index].son[1]) Tree[Tree[index].son[1]].lmax = Tree[Tree[index].son[1]].rmax = Tree[Tree[index].son[1]].Max = max(tmp,Tree[Tree[index].son[1]].size*tmp);
                        if (Tree[index].son[0]) Tree[Tree[index].son[0]].lazy = tmp;
                        if (Tree[index].son[1]) Tree[Tree[index].son[1]].lazy = tmp;
                }
                if (Tree[index].rev) {
                        swap(Tree[index].son[0],Tree[index].son[1]);
                        swap(Tree[Tree[index].son[0]].lmax,Tree[Tree[index].son[0]].rmax);
                        swap(Tree[Tree[index].son[1]].lmax,Tree[Tree[index].son[1]].rmax);
                        Tree[Tree[index].son[0]].rev ^= 1;
                        Tree[Tree[index].son[1]].rev ^= 1;
                        Tree[index].rev = 0;
                }
        }
        inline int query_pos(int x) {
                int index = root;
                while (true) {
                        pushdown(index);
                        if (x > Tree[Tree[index].son[0]].size) {
                                x -= Tree[Tree[index].son[0]].size;
                                if (x == 1) return index;
                                --x;
                                index = Tree[index].son[1];
                        } else index = Tree[index].son[0];
                }        
        }
        inline void clear(int index) {
                Tree[Tree[index].fa].son[get(index)] = 0;
                Tree[index].fa = 0;
                stk.push(index);
                if (Tree[index].son[0]) clear(Tree[index].son[0]);
                if (Tree[index].son[1]) clear(Tree[index].son[1]);    
        }
        inline void Insert(int index) {
                int id;
                int x = query_pos(index),
                        y = query_pos(index+1);
                splay(x,0); splay(y,root);
                id = stk.top(); 
                stk.pop();
                build(id,1,tot);
                Tree[Tree[root].son[1]].son[0] = id;
                Tree[id].fa = Tree[root].son[1];
                update(Tree[root].son[1]);
                update(root);
        }
        inline void rotate(int x) {
                int f = Tree[x].fa,g = Tree[f].fa,
                tmpx = get(x),tmpf = get(f);
                pushdown(f); pushdown(x);
                if (!f) return;
                Tree[f].son[tmpx] = Tree[x].son[tmpx^1];
                if (Tree[x].son[tmpx^1]) Tree[Tree[x].son[tmpx^1]].fa = f;
                Tree[x].son[tmpx^1] = f;
                Tree[f].fa = x;
                Tree[x].fa = g;
                if (g) Tree[g].son[tmpf] = x;
                update(f);
                update(x);
        }
        inline void splay(int x,int pos) {
                int f;
                for (f = Tree[x].fa; (f = Tree[x].fa) != pos; rotate(x)) {
                        if (Tree[f].fa != pos) 
                                rotate(get(f) == get(x) ? (f) : (x));
                }
                if (!pos) root = x;
        }
        inline void modify(int l,int r,int v) {
                int x = query_pos(l-1),
                        y = query_pos(r+1);
                splay(x,0); splay(y,root);
                int tmp = Tree[Tree[root].son[1]].son[0];
                Tree[tmp].val = Tree[tmp].lazy = v;
                Tree[tmp].tot = v * Tree[tmp].size;
                Tree[tmp].lmax = Tree[tmp].rmax = Tree[tmp].Max = max(Tree[tmp].size*v,v);
                update(Tree[root].son[1]);
                update(root);
        }
        inline void reverse(int l,int r) {
                int x = query_pos(l-1),
                        y = query_pos(r+1);
                splay(x,0); splay(y,root);
                Tree[Tree[Tree[root].son[1]].son[0]].rev ^= 1;
                swap(Tree[Tree[Tree[root].son[1]].son[0]].lmax,Tree[Tree[Tree[root].son[1]].son[0]].rmax);
        }
        inline void erase(int l,int r) {
                int x = query_pos(l-1),
                        y = query_pos(r+1);
                splay(x,0); splay(y,root);
                clear(Tree[Tree[root].son[1]].son[0]);
                Tree[Tree[root].son[1]].son[0] = 0;
                update(Tree[root].son[1]);
                update(root);
        }
        int get_sum(int l,int r) {
                int x = query_pos(l-1),
                        y = query_pos(r+1);
                splay(x,0); splay(y,root);
                return Tree[Tree[Tree[root].son[1]].son[0]].tot;
        }
        int max_sum(int l,int r) {
                int x = query_pos(l-1),
                        y = query_pos(r+1);
                splay(x,0); splay(y,root);
                return Tree[Tree[Tree[root].son[1]].son[0]].Max;
        }
} T;

int main() {
        
        read(N); read(M);
        
        for (i = 2; i <= MAXX; i++) stk.push(i);
        
        a[1] = a[N+2] = -INF;
        for (i = 2; i <= N + 1; i++) read(a[i]);
        
        T.Tree[0].lmax = T.Tree[0].rmax = T.Tree[0].Max = -INF;
        T.root = 1;
        T.build(1,1,N+2);
        
        while (M--) {
                scanf("%s",&opt);
                if (opt[0] == 'I') {
                        read(pos); read(tot);
                        for (i = 1; i <= tot; i++) read(a[i]);
                        T.Insert(pos+1);
                        N += tot;
                }    else if (opt[0] == 'D') {
                        read(pos); read(tot);
                        T.erase(pos+1,pos+tot);
                        N -= tot;
                } else if (opt[0] == 'M' && opt[2] == 'K') {
                        read(pos); read(tot); read(val);
                        T.modify(pos+1,pos+tot,val);
                } else if (opt[0] == 'R') {
                        read(pos); read(tot);
                        T.reverse(pos+1,pos+tot);
                } else if (opt[0] == 'G') {
                        read(pos); read(tot);
                        writeln(T.get_sum(pos+1,pos+tot));
                } else if (opt[0] == 'M' && opt[2] == 'X') {
                        writeln(T.max_sum(2,N+1));
                }                          
        }
        
        return 0;
    
}
原文地址:https://www.cnblogs.com/evenbao/p/9196410.html