• POJ 2750 Potted Flower(环形区间最大子段和)


    题目链接

    题目大意

      给一个环,然后求每次修改后的最大子段和,最大子段和不能包含整个子段。

    解题思路

      以往解决环形问题都是通过将两个相同的数组拼接起来实现的,但是这个题如果这么写的话要考虑区间长度问题,很麻烦。
      有一个巧妙的方法,在维护区间最大子段和的同时,再维护一个区间最小子段和,那么考虑两个数组拼接的时候,如果最优解只在左半边或者右半边,那么结果就是维护的最大子段和,如果有交叉,就是区间和-区间最小子段和。可以发现区间最小子段和有三种形式,相应的,去掉之后的区间也有三种形式,可以发现如果剪掉的区间在原来数组的中部,则会剩下前后两个区间,但是因为是环,所以剩下的这两个区间也是连在一起的。

    代码

    const int maxn = 1e6+10;
    struct Tree {
        int l, r, lmax, rmax, lmin, rmin, sum, smax, smin;
    } tree[maxn<<2];
    int n, arr[maxn<<1];
    inline void push_down(int rt) {
        tree[rt].sum = tree[rt<<1].sum+tree[rt<<1|1].sum;
        tree[rt].lmax = max(tree[rt<<1].lmax, tree[rt<<1].sum+tree[rt<<1|1].lmax);
        tree[rt].rmax = max(tree[rt<<1|1].rmax, tree[rt<<1|1].sum+tree[rt<<1].rmax);
        tree[rt].smax = max(max(tree[rt<<1].smax, tree[rt<<1|1].smax), tree[rt<<1].rmax+tree[rt<<1|1].lmax);
        tree[rt].lmin = min(tree[rt<<1].lmin, tree[rt<<1].sum+tree[rt<<1|1].lmin);
        tree[rt].rmin = min(tree[rt<<1|1].rmin, tree[rt<<1|1].sum+tree[rt<<1].rmin);
        tree[rt].smin = min(min(tree[rt<<1].smin, tree[rt<<1|1].smin), tree[rt<<1].rmin+tree[rt<<1|1].lmin);
    }
    void build(int rt, int l, int r) {
        tree[rt].l = l, tree[rt].r = r;
        if (l==r) {
            tree[rt].smin = tree[rt].lmin = tree[rt].rmin = tree[rt].smax = tree[rt].lmax = tree[rt].rmax = tree[rt].sum = arr[l];
            return;
        }
        int mid = (l+r)>>1;
        build(rt<<1, l, mid);
        build(rt<<1|1, mid+1, r);
        push_down(rt);
    }
    void update(int rt, int pos, int val) {
        if (tree[rt].l==tree[rt].r) {
            tree[rt].smin = tree[rt].lmin = tree[rt].rmin = tree[rt].smax = tree[rt].lmax = tree[rt].rmax = tree[rt].sum = val;
            return;
        }
        int mid = (tree[rt].l+tree[rt].r)>>1;
        if (pos<=mid) update(rt<<1, pos, val);
        else update(rt<<1|1, pos, val);
        push_down(rt);
    }
    int main() {
        while(cin >> n) {
            for (int i = 1; i<=n; ++i) scanf("%d", &arr[i]), arr[i+n] = arr[i];
            build(1, 1, n);
            int m; cin >> m;
            while(m--) {
                int a, b; scanf("%d%d", &a, &b);
                update(1, a, b); 
                if (tree[1].smax==tree[1].sum) printf("%d
    ", tree[1].sum-tree[1].smin);
                else printf("%d
    ", max(tree[1].smax, tree[1].sum-tree[1].smin));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    HTML5新增
    【目录】洛谷|CODEVS题解汇总
    【搜索】kkksc03考前临时抱佛脚
    【模拟】压缩技术
    【模拟】爱与愁的一千个伤心的理由
    【搜索】棋盘
    【模拟】图书管理员
    【递归】对称二叉树
    【题单】挖坑大行动
    【模拟】弹珠游戏
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/13828645.html
Copyright © 2020-2023  润新知