zoukankan      html  css  js  c++  java
  • GSS3

    题意翻译

    nnn 个数, qqq 次操作

    操作0 x yAxA_xAx 修改为 yyy

    操作1 l r询问区间 [l,r][l, r][l,r] 的最大子段和

    感谢 @Edgration 提供的翻译

    题目描述

    You are given a sequence A of N (N <= 50000) integers between -10000 and 10000. On this sequence you have to apply M (M <= 50000) operations:
    modify the i-th element in the sequence or for given x y print max{Ai + Ai+1 + .. + Aj | x<=i<=j<=y }.

    输入输出格式

    输入格式:

    The first line of input contains an integer N. The following line contains N integers, representing the sequence A1..AN.
    The third line contains an integer M. The next M lines contain the operations in following form:
    0 x y: modify Ax into y (|y|<=10000).
    1 x y: print max{Ai + Ai+1 + .. + Aj | x<=i<=j<=y }.

    输出格式:

    For each query, print an integer as the problem required.

    输入输出样例

    输入样例#1: 
    4
    1 2 3 4
    4
    1 1 3
    0 3 -3
    1 2 4
    1 3 3
    输出样例#1: 
    6
    4
    -3


    提交地址 : luogu SP1716
    spoj;

    分析:
    线段树水题


    用线段树维护四个值 : 这一区间的最大子段和, 这一区间的从最左端开始的最大子段和, 从右端开始的最大子段和,还有这一段的和;
    怎么维护?
    	t[o].sum = t[ls(o)].sum + t[rs(o)].sum;
    	t[o].lsum = max(t[ls(o)].lsum, t[ls(o)].sum + t[rs(o)].lsum);
    	t[o].rsum = max(t[rs(o)].rsum, t[rs(o)].sum + t[ls(o)].rsum);
    	t[o].dat = max(t[ls(o)].rsum + t[rs(o)].lsum, max(t[ls(o)].dat, t[rs(o)].dat));
    

     就解释一个:你左端开始的最大子段和一定是你左二子的左端点开始的最大子段和, 还有左二子全选加上右儿子的左端开始的最大子段和;

    其他的都大同小异;

    一样的按照普通线段树写;

    主要讲讲查询操作;

    因为我们要找一个连续的序列,而不是每个dat取max;

    所以我们要维护一个前缀和qzh;

    因为我们维护的是前缀和, 所以每次可以用 qzh+t[o].lsum 和 t[o].dat 取max来更新ans;

    然后我们再改变qzh的值 在 qzh + t[o].sum 和 t[o].rsum中取max;

    代码奉上:

    //zZhBr
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define int long long
    
    inline int read()
    {
        int res=0;bool flag=0;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')flag=1;ch=getchar();};
        while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch-'0');ch=getchar();}
        return flag?-res:res;
    }
    
    const int N = 50005;
    
    int n, a[N], m;
    int ans, qzh;
    
    struct Segment
    {
        int ls, rs;
        int l, r;
        int sum;
        int lsum, rsum;
        int dat;
    }t[N<<1];
    int cnt = 1;
    int root;
    #define ls(x) t[x].ls
    #define rs(x) t[x].rs
    
    inline void pushup(int o)
    {
        t[o].l = t[ls(o)].l, t[o].r = t[rs(o)].r;
        t[o].sum = t[ls(o)].sum + t[rs(o)].sum;
        t[o].lsum = max(t[ls(o)].lsum, t[ls(o)].sum + t[rs(o)].lsum);
        t[o].rsum = max(t[rs(o)].rsum, t[rs(o)].sum + t[ls(o)].rsum);
        t[o].dat = max(t[ls(o)].rsum + t[rs(o)].lsum, max(t[ls(o)].dat, t[rs(o)].dat));
    }
    
    inline void build(int l, int r, int o)
    {
        if (l == r)
        {
            t[o].sum = a[l];
            t[o].lsum = a[l];
            t[o].rsum = a[l];
            t[o].dat = a[l];
            t[o].l = t[o].r = l;
            return;
        }
        
        int mid = l + r >> 1;
        t[o].ls = cnt++;
        t[o].rs = cnt++;
        build(l, mid, ls(o));
        build(mid + 1, r, rs(o));
        pushup(o);
    }
    
    inline void change(int o, int x, int v)
    {
        if (t[o].l == t[o].r)
        {
            t[o].sum = v;
            t[o].dat = v;
            t[o].lsum = t[o].rsum = v;
            return;
        }
        
        int mid = t[o].l + t[o].r >> 1;
        
        if (x <= mid) change(ls(o), x, v);
        else change(rs(o), x, v);
        pushup(o);
    }
    
    inline void query(int o, int li, int ri)
    {    
        if (li <= t[o].l and ri >= t[o].r) 
        {
            ans = max(ans, max(qzh + t[o].lsum, t[o].dat));
            qzh = max(qzh + t[o].sum, t[o].rsum);
            return;
        }
        int res = 0;
        int mid = t[o].r + t[o].l >> 1;
        if (li <= mid) query(ls(o), li, ri);
        if (ri > mid) query(rs(o), li, ri);    
    }
    
    signed main()
    {
        n = read();
        for (register int i = 1 ; i <= n ; i ++) a[i] = read();
        m = read();
        root = cnt++;
        build(1, n, root);
        
        while (m--)
        {
            int opt = read();
            int x = read(), y = read();
            
            if (opt == 0)
            {
                change(root, x, y);
            }
            else 
            {
                ans = -1e9, qzh = -1e9;
                query(root, x, y);
                printf("%lld
    ", ans);
            }
        }
        
        return 0;
        
    }
  • 相关阅读:
    火狐插件火狐黑客插件将Firefox变成黑客工具的七个插件
    memcache安装环境:WINDOWS 7
    PHP正则表达式
    968. 监控二叉树 力扣(困难) dfs 官方说DP
    375. 猜数字大小 II 力扣(中等) 区间动态规划、记忆化搜索
    629. K个逆序对数组 力扣(困难) 区间动态规划
    剑指 Offer 51. 数组中的逆序对 力扣(困难) 巧用归并排序算法
    488. 祖玛游戏 力扣(困难) dfs
    16. 最接近的三数之和 力扣(中等) 双指针
    319. 灯泡开关 力扣(中等) 数论
  • 原文地址:https://www.cnblogs.com/BriMon/p/9112431.html
Copyright © 2011-2022 走看看