• FJUT3568 中二病也要敲代码(线段树维护区间连续最值)题解


    题意:有一个环,有1~N编号,m次操作,将a位置的值改为b,问你这个环当前最小连续和多少(不能全取也不能不取)

    思路:用线段树维护一个区间最值连续和。我们设出两个变量Lmin,Rmin,Mmin表示区间左边最小连续和,右边最小连续和,区间最小连续和,显然这可以通过这个方式更新维护。

    现在我们已经可以维护一个区间最值连续和了,那么怎么求“环”的最小连续和呢?显然如果最小区间横跨1和n是不能表示出来的(比如最小区间是2,1,n,n-1之和),那么我们可以转化为求sum-Mmax即区间和减去区间最大值,那么显然最终答案是min( sum[1] - Mmax[1], Mmin[1] ),但由题意“不能全取也不能不取”,那么特判。

    好久没做线段树维护连续区间的题了...

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<cmath>
    #include<map>
    #include<set>
    #include<vector>
    using namespace std;
    #define inf 0x3f3f3f3f
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define mem(a,b) memset(a,b,sizeof(a));
    #define lowbit(x)  x&-x;
    typedef long long ll;
    typedef unsigned long long ull;
    const double eps = 1e-6;
    const int maxn = 1e5+5;
    const ll mod = 1e8+7;
    ll Lmax[maxn << 2], Rmax[maxn << 2], Mmax[maxn << 2], sum[maxn << 2];
    ll Lmin[maxn << 2], Rmin[maxn << 2], Mmin[maxn << 2];
    ll a[maxn];
    void push_up(int rt){
        Lmax[rt] = max(Lmax[rt << 1], sum[rt << 1] + Lmax[rt << 1 | 1]);
        Rmax[rt] = max(Rmax[rt << 1 | 1], sum[rt << 1 | 1] + Rmax[rt << 1]);
        Mmax[rt] = max(max(Mmax[rt << 1], Mmax[rt << 1 | 1]), Rmax[rt << 1] + Lmax[rt << 1 | 1]);
        Lmin[rt] = min(Lmin[rt << 1], sum[rt << 1] + Lmin[rt << 1 | 1]);
        Rmin[rt] = min(Rmin[rt << 1 | 1], sum[rt << 1 | 1] + Rmin[rt << 1]);
        Mmin[rt] = min(min(Mmin[rt << 1], Mmin[rt << 1 | 1]), Rmin[rt << 1] + Lmin[rt << 1 | 1]);
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    }
    void build(int l, int r, int rt){
        if(l == r){
            Mmax[rt] = Rmax[rt] = Lmax[rt] = Mmin[rt] = Rmin[rt] = Lmin[rt] = sum[rt] = a[l];
            return;
        }
        int m = (l + r) >> 1;
        build(l, m, rt << 1);
        build(m + 1, r, rt << 1 | 1);
        push_up(rt);
    }
    void update(int pos, int l, int r, int v, int rt){
        if(l == r){
            Mmax[rt] = Rmax[rt] = Lmax[rt] = Mmin[rt] = Rmin[rt] = Lmin[rt] = sum[rt] = v;
            return;
        }
        int m = (l + r) >> 1;
        if(pos <= m)
            update(pos, l, m, v, rt << 1);
        else
            update(pos, m + 1, r, v, rt << 1 | 1);
        push_up(rt);
    }
    int main(){
        int n, m, A;
        ll B;
        while(~scanf("%d", &n)){
            for(int i = 1; i <= n; i++){
                scanf("%lld", &a[i]);
            }
            build(1, n, 1);
            scanf("%d", &m);
            while(m--){
                ll MAX, MIN, ans;
                scanf("%d%lld", &A, &B);
                update(A, 1, n, B, 1);
                if(Mmax[1] == sum[1]){
                    ans = Mmin[1];
                }
                else if(Mmin[1] == sum[1]){
                    ans = Mmin[1] - Mmax[1];
                }
                else{
                    ans = min(sum[1] - Mmax[1], Mmin[1]);
                }
                printf("%lld
    ", ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    codeforces 455C 并查集
    poj 3501 Escape from Enemy Territory 预处理+二分+bfs
    POJ 2110 Mountain Walking 二分+bfs
    poj1637 Sightseeing tour 混合图欧拉回路判定
    ubuntu禁用super(win)键
    win10 ubuntu双系统安装后无法引导进入ubuntu
    python2限制函数传入的关键字参数
    python限制函数执行时间
    python classmethod 和 staticmethod的区别
    centos sendmail 启动慢
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9886137.html
Copyright © 2020-2023  润新知