动态的最大子段和

就是splay啊,说一下GSS1吧,维护四个值,一个是这个区间和(下面说sum),

一个是从左边开始的最大和(下面说ls)和右边开始的最大和(下面说rs),

还有一个就是最大区间和(mx),那么

$$ls = max(leftson -> ls, leftson -> sum + rightson -> ls)$$

$$rs = ......$$

$$sum = leftson -> sum + rightson -> sum$$

$$mx = max(leftson -> sum, max(rightson -> sum, leftson ->
rs + rightson -> ls ))$$

就是这样,然后再伸展树里各种特判,一个也不可以少考虑

然后就是这道题至少选一个数啊

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
struct Node{
    Node *ch[2];
    int s, v, ls, rs, sum, ans, k, f;

    inline int cmp(int x){
        int o = 0;
        if(ch[0] != NULL){
            if(ch[0] -> s >= x) return 0;
            o += ch[0] -> s;
        }
        if(o + 1 == x) return -1;
        return 1;
    }

    inline void maintain(){
        int yy, yt;

        s = 1;
        if(ch[0]) s += ch[0] -> s;
        if(ch[1]) s += ch[1] -> s;

        sum = v;
        if(ch[0]) sum += ch[0] -> sum;
        if(ch[1]) sum += ch[1] -> sum;

        ls = -214748364;
        if(ch[0]) ls = max(ls, ch[0] -> ls);
        yy = v;
        if(ch[0]) yy += ch[0] -> sum;
        yt = 0;
        if(ch[1]) yt = ch[1] -> ls;
        ls = max(ls, max(yy, yy + yt));

        rs = -214748364;
        if(ch[1]) rs = max(rs, ch[1] -> rs);
        yy = v;
        if(ch[1]) yy += ch[1] -> sum;
        yt = 0;
        if(ch[0]) yt = ch[0] -> rs;
        rs = max(rs, max(yy, yy + yt));

        ans = v;
        if(ch[0]) ans = max(ans, ch[0] -> ans);
        if(ch[1]) ans = max(ans, ch[1] -> ans);
        yy = 0;
        if(ch[0]) yy = ch[0] -> rs;
        yt = 0;
        if(ch[1]) yt = ch[1] -> ls;
        ans = max(ans, max(yy + yt + v, max(yy + v, yt + v)));
        return;
    }

    inline void pushdown(){
        if(f == 1){
            if(ch[0]){
                swap(ch[0] -> ch[0], ch[0] -> ch[1]);
                ch[0] -> f ^= 1;
                swap(ch[0] -> ls, ch[0] -> rs);
            }

            if(ch[1]){
                swap(ch[1] -> ch[0], ch[1] -> ch[1]);
                ch[1] -> f ^= 1;
                swap(ch[1] -> ls, ch[1] -> rs);
            }

            f = 0;
        }

        if(k != -214748364){
            if(ch[0]){
                ch[0] -> f = 0;
                ch[0] -> v = k;
                ch[0] -> sum = ch[0] -> s * k;
                if(k > 0){
                    ch[0] -> ls = ch[0] -> rs = ch[0] -> ans = ch[0] -> s * k;
                }
                else{
                    ch[0] -> ls = ch[0] -> rs = ch[0] -> ans = k;
                }
                ch[0] -> k = k;
            }

            if(ch[1]){
                ch[1] -> f = 0;
                ch[1] -> v = k;
                ch[1] -> sum = ch[1] -> s * k;
                if(k > 0){
                    ch[1] -> ls = ch[1] -> rs = ch[1] -> ans = ch[1] -> s * k;
                }
                else{
                    ch[1] -> ls = ch[1] -> rs = ch[1] -> ans = k;
                }
                ch[1] -> k = k;
            }   

            k = -214748364;
        }
    }

};
struct splay_tree{
    int a[500000];
    int size;
    Node* p;

    inline void init(){
        size = 0;
        return;
    }

    inline void rotate(Node* &o, int d){
        Node *k = o -> ch[d ^ 1];
        k -> pushdown();
        o -> ch[d ^ 1] = k -> ch[d];
        k -> ch[d] = o;
        o -> maintain();
        k -> maintain();
        o = k;
        return;
    }

    inline void splay(Node* &o, int k){
        o -> pushdown();
        int d = o -> cmp(k);
        if(d == 1 && o -> ch[0] != NULL) k = k - o -> ch[0] -> s - 1;
        else if(d == 1) k --;
        if(d != -1){
            Node* w = o -> ch[d];
            w -> pushdown();
            int d2 = w -> cmp(k);
            int k2 = k;
            if(d2 != 0){
                k2 --;
                if(w -> ch[0] != NULL){
                    k2 -= w -> ch[0] -> s;
                }
            }
            if(d2 != -1){
                splay(w -> ch[d2], k2);
                if(d == d2) rotate(o, d ^ 1);
                else rotate(o -> ch[d], d);
            }
            rotate(o, d ^ 1);
        }
        o -> maintain();
        return;
    }

    inline Node* merge(Node *left, Node *right){
        if(left == NULL) return right;
        if(right == NULL) return left;
        splay(left, left -> s);
        left -> ch[1] = right;
        left -> maintain();
        return left;
    }

    inline void split(Node* &o, int k, Node* &left, Node* &right){
        if(k == 0){
            left = NULL;
            right = o;
            return;
        }
        splay(o, k);
        left = o;
        right = o -> ch[1];
        left -> ch[1] = NULL;
        left -> maintain();
        return;
    }

    inline void insert(Node* &o, int l, int r){
        if(r < l) return;
        int mid = (l + r) / 2;
        o = new Node();
        o -> ch[0] = o -> ch[1] = NULL;
        o -> v = a[mid];
        o -> f = 0;
        o -> k = -214748364;
        if(l != r){
            insert(o -> ch[0], l, mid - 1);
            insert(o -> ch[1], mid + 1, r);
        }
        o -> maintain();
        return;
    }

    inline void add(int pos, int tot){
        Node *left, *mid, *right;
        split(p, pos, left, right);
        insert(mid, 1, tot);
        p = merge(left, merge(mid, right));
        return;
    }

    inline void delete_splay_tree(Node* &o){
        if(o -> ch[0] != NULL) delete_splay_tree(o -> ch[0]);
        if(o -> ch[1] != NULL) delete_splay_tree(o -> ch[1]);
        delete o;
        return;
    }

    inline void Delete(int pos, int l){
        Node *left, *mid, *right;
        split(p, pos - 1, left, mid);
        split(mid, l, mid, right);
        delete_splay_tree(mid);
        left = merge(left, right);
        p = left;
        return;
    }

    inline void flip(Node* &o, int l, int r){
        Node *left, *mid, *right;
        split(p, l - 1, left, mid);
        split(mid, r, mid, right);
        swap(mid -> ch[0], mid -> ch[1]);
        mid -> f ^= 1;
        swap(mid -> ls, mid -> rs);
        p = merge(left, merge(mid, right));
        return;
    }

    inline void make_same(Node* &o, int l, int r, int c){
        Node *left, *mid, *right;
        split(p, l - 1, left, mid);
        split(mid, r, mid, right);
        mid -> v = c;
        mid -> sum = mid -> s * c;
        if(c > 0){
            mid -> ls = mid -> rs = mid -> ans = mid -> s * c;
        }
        else{
            mid -> ls = mid -> rs = mid -> ans = c;
        }
        mid -> k = c;
        p = merge(left, merge(mid, right));
        return;
    }

    inline int query_sum(Node* &o, int l, int r){
        if(r == 0) return 0;
        Node *left, *mid, *right;
        split(p, l - 1, left, mid);
        split(mid, r, mid, right);
        int ret = mid -> sum;
        p = merge(left, merge(mid, right));
        return ret;
    }

    inline int query_boss(Node* &o){
        return o -> ans;
    }

} wt;
int main(){
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++){
        scanf("%d", &wt.a[i]);
    }
    wt.insert(wt.p, 1, n);
    char str[100];
    int pos, tot, c;
    for(int i = 1; i <= m; i ++){
        scanf("%s", str);
        if(str[0] == 'I'){
            scanf("%d%d", &pos, &tot);
            for(int j = 1; j <= tot; j ++) scanf("%d", &wt.a[j]);
            if(tot == 0) continue;
            wt.add(pos, tot);
        }
        else if(str[0] == 'D'){
            scanf("%d%d", &pos, &tot);
            if(tot == 0) continue;
            wt.Delete(pos, tot);
        }
        else if(str[2] == 'K'){
            scanf("%d%d%d", &pos, &tot, &c);
            if(tot == 0) continue;
            wt.make_same(wt.p, pos, tot, c);
        }
        else if(str[0] == 'R'){
            scanf("%d%d", &pos, &tot);
            if(tot == 0) continue;
            wt.flip(wt.p, pos, tot);
        }
        else if(str[0] == 'G'){
            scanf("%d%d", &pos, &tot);
            printf("%d\n", wt.query_sum(wt.p, pos, tot));
        }
        else{
            int ret = wt.query_boss(wt.p);
            printf("%d\n", ret);
        }
        //printf("%d:%d\n", i, wt.p -> s);
    }
    return 0;
}

BZOJ1500——维修序列的更多相关文章

  1. [bzoj1269]文本编辑器editor [bzoj1500]维修数列

    1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2540 Solved: 923 [Submit ...

  2. BZOJ1500 维修数列

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1500 [前言] 据说没打这题就相当于没打过Splay,这题简直就是让你内心崩溃的... 这 ...

  3. [bzoj1500 维修数列](NOI2005) (splay)

    真的是太弱了TAT...光是把代码码出来就花了3h..还调了快1h才弄完T_T 号称考你会不会splay(当然通过条件是1h内AC..吓傻)... 黄学长的题解:http://hzwer.com/28 ...

  4. bzoj 1500 维修序列

    Written with StackEdit. Description 请写一个程序,要求维护一个数列,支持以下 \(6\) 种操作: 请注意,格式栏 中的下划线' _ '表示实际输入文件中的空格 I ...

  5. 可持久化Treap(fhq Treap,非旋转式Treap)学习(未完待续)

    简介:     Treap,一种表现优异的BST 优势:     其较于AVL.红黑树实现简单,浅显易懂     较于Splay常数小,通常用于树套BST表现远远优于Splay     或许有人想说S ...

  6. 【splay模板】

    #include <iostream> #include <cstring> #include <algorithm> #include <cstdio> ...

  7. 关于oi

    2015-12-26 今天在机房,楼上的孩子发下来一个exe,善良无知的我打开了那个exe,然后电脑就关机了.萌萌的辅导老师看到之后就不再萌萌哒,他跑到五楼训斥了那群孩子们一顿(自行脑补).出于报复, ...

  8. 个人整理的数组splay板子,指针的写的太丑了就不放了。。

    splay的板子.. 由于被LCT榨干了..所以昨天去学了数组版的splay,现在整理一下板子.. 以BZOJ3224和3223为例题..暂时只有这些,序列的话等有时间把维修序列给弄上来!! BZOJ ...

  9. POJ3580 SuperMemo

    Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to pl ...

随机推荐

  1. CSS的4种引入方式及优先级

    第一:css的四种引入方式 1.行内样式 最直接最简单的一种,直接对HTML标签使用style="",例如: <p style="color:#F00; " ...

  2. 开发板ping不通主机和虚拟机的看过来(转载)!

    前几天在做uboot下用tftp下载文件到开发板的实验时,为了能解决开发板ping不通主机和虚拟机的问题,可谓绞尽脑汁,正所谓久病成医,虽然为了这一小问题废了我那么长时间,但我在解决问题的同时也学到了 ...

  3. 异步-学习笔记3 Task

    1. 通过Task启动多线程 2. 解决多线程的几大应用场景 private void btnTask_Click(object sender, EventArgs e) { Console.Writ ...

  4. 在Linux下安装和使用MySQL

    [简 介] 想使用Linux已经很长时间了,由于没有硬性任务一直也没有系统学习,近日由于工作需要必须使用Linux下的MySQL.本以为有Windows下使用SQL Server的经验,觉得在Linu ...

  5. WinForm------GridControl的部分属性介绍

    参考其它链接: http://www.cnblogs.com/djian/archive/2010/11/19/1881579.html //注意:在定义GridControl里面的FileName里 ...

  6. 批处理学习:for语句详解【经典】

    大纲 一 前言 二 for语句的基本用法 三 for /f (delims.tokens.skip.eol.userbackq.变量延迟) 四 for /r (递归遍历) 五 for /d (遍历目录 ...

  7. Linux 命令小记

    1. pidof 进程名 :获取进程的pid,例如 pidof memcached 得到5333 2. unset Shell变量 :取消设置一个shell变量,从内存和shell的导出环境中删除它, ...

  8. Winsock 入门 判读主机字节序 示例

    #include <stdio.h> union endian_u { /*最大成员的长度就是联合成员的长度.联合可以在定义时直接进行初始化,但这个初始化必须是联合第一个成员的类型,所以把 ...

  9. 几个有用的JavaScript/jQuery代码片段(转)

    1. 检查数据是否包含在Array中 //jQuery实现 jQuery.inArray("value", arr); // 使用方法: if( jQuery.inArray(&q ...

  10. iTunes访问自己应用的沙盒