bzoj3638 Cf172 k-Maximum Subsequence Sum

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3638

【题解】

看到k<=20就感觉很py了啊

我们用一棵线段树维护选段的过程,能选到>0的段就一直选,直到选到<0的段,每次选完把段内的数全部取相反数,意为下次取是“不取”的意思。

用线段树维护左边/右边/中间的max/min

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n;

struct pa {
    int l, r, x;
    pa() {}
    pa(int l, int r, int x) : l(l), r(r), x(x) {}
    friend pa operator + (pa a, pa b) {
        pa c; c.x = a.x + b.x;
        c.l = a.l, c.r = b.r;
        return c;
    }
    friend bool operator < (pa a, pa b) {
        return a.x < b.x;
    }
    friend bool operator > (pa a, pa b) {
        return a.x > b.x;
    }
};

struct querys {
    pa lmx, rmx, mx, s;
    querys() {}
    querys(pa lmx, pa rmx, pa mx, pa s) : lmx(lmx), rmx(rmx), mx(mx), s(s) {}
};

namespace SMT {
    const int Ms = 1e6 + 10;
    pa lmx[Ms], rmx[Ms], lmi[Ms], rmi[Ms], mx[Ms], mi[Ms], s[Ms];
    bool tag[Ms];        // -1
    # define ls (x<<1)
    # define rs (x<<1|1)
    inline void up(int x) {
        if(!x) return ;
        lmx[x] = max(lmx[ls], s[ls] + lmx[rs]);
        lmi[x] = min(lmi[ls], s[ls] + lmi[rs]);
        rmx[x] = max(rmx[rs], rmx[ls] + s[rs]);
        rmi[x] = min(rmi[rs], rmi[ls] + s[rs]);
        mx[x] = max(mx[ls], mx[rs]);
        mx[x] = max(mx[x], rmx[ls] + lmx[rs]);
        mi[x] = min(mi[ls], mi[rs]);
        mi[x] = min(mi[x], rmi[ls] + lmi[rs]);
        s[x] = s[ls] + s[rs];
    }
    inline void pushtag(int x) {
        if(!x) return ;
        lmx[x].x = -lmx[x].x;
        rmx[x].x = -rmx[x].x;
        lmi[x].x = -lmi[x].x;
        rmi[x].x = -rmi[x].x;
        mx[x].x = -mx[x].x;
        mi[x].x = -mi[x].x;
        s[x].x = -s[x].x;
        swap(mx[x], mi[x]);
        swap(lmx[x], lmi[x]);
        swap(rmx[x], rmi[x]);
        tag[x] ^= 1;
    }
    inline void down(int x) {
        if(!x) return ;
        if(!tag[x]) return ;
        pushtag(ls); pushtag(rs);
        tag[x] = 0;
    }
    inline void change(int x, int l, int r, int ps, int d) {
        if(l == r) {
            s[x].l = s[x].r = lmx[x].l = lmx[x].r = rmx[x].l = rmx[x].r = lmi[x].l = lmi[x].r = rmi[x].l = rmi[x].r = l;
            mx[x].l = mx[x].r = mi[x].l = mi[x].r = l;
            s[x].x = mx[x].x = mi[x].x = lmx[x].x = lmi[x].x = rmx[x].x = rmi[x].x = d;
            tag[x] = 0;
            return ;
        }
        down(x);
        int mid = l+r>>1;
        if(ps <= mid) change(ls, l, mid, ps, d);
        else change(rs, mid+1, r, ps, d);
        up(x);
    }

    inline void change2(int x, int l, int r, int L, int R) {
        if(L <= l && r <= R) {
            pushtag(x);
            return ;
        }
        down(x);
        int mid = l+r>>1;
        if(L <= mid) change2(ls, l, mid, L, R);
        if(R > mid) change2(rs, mid+1, r, L, R);
        up(x);
    }

    inline querys merge(querys a, querys b) {
        querys c;
        c.lmx = max(a.lmx, a.s+b.lmx);
        c.rmx = max(b.rmx, a.rmx+b.s);
        c.s = a.s + b.s;
        c.mx = max(a.mx, b.mx);
        c.mx = max(c.mx, a.rmx + b.lmx);
        return c;
    }

    inline querys query(int x, int l, int r, int L, int R) {
        if(L <= l && r <= R) return querys(lmx[x], rmx[x], mx[x], s[x]);
        down(x);
        int mid = l+r>>1;
        if(R <= mid) return query(ls, l, mid, L, R);
        else if(L > mid) return query(rs, mid+1, r, L, R);
        else return merge(query(ls, l, mid, L, mid), query(rs, mid+1, r, mid+1, R));
    }

    inline void debug(int x, int l, int r) {
        printf("x = %d, l = %d, r = %d : mx = %d, lmx = %d, rmx = %d\n", x, l, r, mx[x].x, mx[x].l, mx[x].r);
        if(l == r) return ;
        int mid = l+r>>1;
        debug(ls, l, mid);
        debug(rs, mid+1, r);
    }
}

int Left[233], Right[233], m;

int main() {
    cin >> n;
    for (int i=1, t; i<=n; ++i) {
        scanf("%d", &t);
        SMT::change(1, 1, n, i, t);
    }
    int Q, a, b, c;
    querys t;
    cin >> Q;
    while(Q--) {
        int opt; scanf("%d", &opt);
        if(!opt) {
            scanf("%d%d", &a, &b);
            SMT::change(1, 1, n, a, b);
        } else {
            scanf("%d%d%d", &a, &b, &c);
            int s = 0; m = 0;
            while(c--) {
                t = SMT::query(1, 1, n, a, b);
                if(t.mx.x < 0) break;
                else s += t.mx.x;
//                cout << t.mx.l << " " << t.mx.r << " " << t.mx.x << endl;
                SMT::change2(1, 1, n, t.mx.l, t.mx.r);
                ++m; Left[m] = t.mx.l, Right[m] = t.mx.r;
            }
            printf("%d\n", s);
            for (int i=m; i; --i) SMT::change2(1, 1, n, Left[i], Right[i]);
        }
//        SMT::debug(1, 1, n);
    }
    return 0;
}

时间: 2024-10-05 20:26:58

bzoj3638 Cf172 k-Maximum Subsequence Sum的相关文章

Maximum Subsequence Sum - 最大子列和问题_C语言实现

第一次写这方面的blog.自己也是初次接触相关知识,写的有不妥的地方十分欢迎大家指正~ 这是浙大PAT上的一道算法题(据说是浙大04年研究生复试题),题目是这样的: Maximum Subsequence Sum Given a sequence of KK integers { N_1N?1??, N_2N?2??, ..., N_KN?K?? }. A continuous subsequence is defined to be { N_iN?i??, N_{i+1}N?i+1??, ..

Maximum Subsequence Sum 最大子序列和的进击之路

本文解决最大子序列和问题,有两个题目组成,第二个题目比第一个要求多一些(其实就是要求输出子序列首尾元素). 01-复杂度1 最大子列和问题   (20分) 给定KK个整数组成的序列{ N1??, N2??, ..., NK?? },"连续子列"被定义为{ N?i??, Ni+1 ..., Nj },其中 1≤i≤j≤K."最大子列和"则被定义为所有连续子列元素的和中最大者.例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4,

pat1007. Maximum Subsequence Sum (25)

1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is defined to be { Ni, Ni+1, ..., Nj } where 1 <= i <= j <= K. The

1007. Maximum Subsequence Sum (25)——PAT (Advanced Level) Practise

题目信息: 1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is defined to be { Ni, Ni+1, ..., Nj } where 1 <= i <= j <=

1007 Maximum Subsequence Sum (25)(25 分)

1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A continuous subsequence is defined to be { N~i~, N~i+1~, ..., N~j~ } where 1 <= i <= j <= K. The Maximum Subsequence is the continuous subsequence

1007 Maximum Subsequence Sum(25 分)

1007 Maximum Subsequence Sum(25 分) Given a sequence of K integers { N?1??, N?2??, ..., N?K?? }. A continuous subsequence is defined to be { N?i??, N?i+1??, ..., N?j?? } where 1≤i≤j≤K. The Maximum Subsequence is the continuous subsequence which has th

[PTA] PAT(A) 1007 Maximum Subsequence Sum (25 分)

目录 Problem Description Input Output Sample Sample Input Sample Output Solution Analysis Code Problem portal: 1007 Maximum Subsequence Sum (25 分) Description Given a sequence of $K$ integers { $N_{1}?$, $N_{2}?$, $...$, $N_{K}$ }. A continuous subsequ

1007 Maximum Subsequence Sum (25分) 求最大连续区间和

1007 Maximum Subsequence Sum (25分) Given a sequence of K integers { N?1??, N?2??, ..., N?K?? }. A continuous subsequence is defined to be { N?i??, N?i+1??, ..., N?j?? } where 1≤i≤j≤K. The Maximum Subsequence is the continuous subsequence which has th

Algorithm for Maximum Subsequence Sum z

MSS(Array[],N)//Where N is the number of elements in array { sum=0; //current sum max-sum=0;//Maximum Sum seq-start=0;//start of the subsequence seq-end=0;//end of the subsequence for(i=0;i<N;i++){ sum=sum+Array[i]; if(sum<0){ sum=0; seq-start++; }

dynamic programming 之Maximum Sub-Sequence Sum(最大子序列和问题)

问题描述: 给定一个整数序列, 序列中可能有负数. 目的是找出这个序列的连续子序列(即子序列的元素的选取是连续的从序列中选取的).即通过确定i, j 的值,  使得的值达到最大. 我们定义, 当所有的元素为负数值的时候, 那么maximum subsequence sum 为0. 下面我们用动态规划的技术去求解. 为了找到最大连续子序列和,  不难看出, 在扩展我们的求和窗口的时候, 当新加进窗口的元素市负数的时候, 只要我们得到的新的求和窗口的值求和不是负数, 那么我们就不能丢掉这个新的负数.