zoukankan      html  css  js  c++  java
  • 【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;
        
    }
  • 相关阅读:
    MySQL >>> 存储引擎
    MySQL >>> 基本操作语句
    MySQL >>> 使用安装
    协程 *单线程实现并发
    进程池 & 线程池
    线程 *知识点扩充
    进程 & 线程
    DRF单表序列化
    DRF
    接口规范
  • 原文地址:https://www.cnblogs.com/evenbao/p/9196410.html
Copyright © 2011-2022 走看看