SP1716 GSS3 - Can you answer these queries III(单点修改,区间最大子段和)

题意翻译

nnn 个数, qqq 次操作

操作0 x y把 AxA_xAx? 修改为 yyy

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

题目描述

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.

思路:

这道题与GSS1很像(没做过GSS1的点这里

但这个题怎么办呢?

大家应该记得,我做GSS1时,并没有建树这个步骤

而是直接将原始节点都变为-inf,然后通过单点修改的方式建树

那么GSS3就很简单了

我们不需要动修改函数(因为都是单点)

直接在循环中引用即可(我才不会告诉你我是先写的GSS3)

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define rii register int i
#define rij register int j
#define inf 1073741824
#define rs 65536
using namespace std;
struct nod{
    int lm,rm,maxn,sum;
}x[6000005];
int n,q,cz,x1,y1;
void add(int wz,int l,int r,int val,int bh)
{
    if(l==r&&l==wz)
    {
        x[bh].maxn=val;
        x[bh].lm=val;
        x[bh].rm=val;
        x[bh].sum=val;
        return;
    }
    int ltt=(l+r)/2;
    if(wz<=ltt)
    {
        add(wz,l,ltt,val,bh*2);
    }
    else
    {
        add(wz,ltt+1,r,val,bh*2+1);
    }
    x[bh].sum=x[bh*2].sum+x[bh*2+1].sum;
    x[bh].lm=max(x[bh*2].lm,x[bh*2].sum+x[bh*2+1].lm);
    x[bh].rm=max(x[bh*2+1].rm,x[bh*2+1].sum+x[bh*2].rm);
    x[bh].maxn=max(x[bh*2].maxn,max(x[bh*2+1].maxn,x[bh*2].rm+x[bh*2+1].lm));
}
nod query(int l,int r,int nl,int nr,int bh)
{
    nod an,bn;
    if(l<nl)
    {
        l=nl;
    }
    if(r>nr)
    {
        r=nr;
    }
    if(nl==l&&nr==r)
    {
        an=x[bh];
        return an;
    }
    int ltt=(nl+nr)/2;
    if(l<=ltt&&r<=ltt)
    {
        return an=query(l,r,nl,ltt,bh*2);
    }
    if(r>ltt&&l>ltt)
    {
        return bn=query(l,r,ltt+1,nr,bh*2+1);
    }
    else
    {
        an=query(l,r,nl,ltt,bh*2);
        bn=query(l,r,ltt+1,nr,bh*2+1);
        an.maxn=max(an.maxn,max(bn.maxn,an.rm+bn.lm));
        an.lm=max(an.lm,an.sum+bn.lm);
        an.rm=max(bn.rm,bn.sum+an.rm);
        an.sum=an.sum+bn.sum;
        return an;
    }

}
int main()
{
//    freopen("brs.in","r",stdin);
//    freopen("brs.out","w",stdout);
    for(rii=1;i<=150005;i++)
    {
        x[i].lm=-inf;
        x[i].rm=-inf;
        x[i].maxn=-inf;
    }
    scanf("%d",&n);
    for(rii=1;i<=n;i++)
    {
        int ltt;
        scanf("%d",&ltt);
        add(i,1,rs,ltt,1);
    }
    scanf("%d",&q);
    for(rii=1;i<=q;i++)
    {
        scanf("%d%d%d",&cz,&x1,&y1);
        if(cz==1)
        {
            nod ans=query(x1,y1,1,rs,1);
            printf("%d\n",ans.maxn);
        }
        else
        {
            add(x1,1,rs,y1,1);
        }
    }
}

原文地址:https://www.cnblogs.com/ztz11/p/9343435.html

时间: 2024-11-09 10:41:50

SP1716 GSS3 - Can you answer these queries III(单点修改,区间最大子段和)的相关文章

线段树 SP1716 GSS3 - Can you answer these queries III

SP1716 GSS3 - Can you answer these queries III 题意翻译 n 个数,q 次操作 操作0 x y把A_xAx 修改为yy 操作1 l r询问区间[l, r] 的最大子段和 依旧是维护最大子段和,还是再敲一遍比较好. code: #include<iostream> #include<cstdio> #define ls(o) o<<1 #define rs(o) o<<1|1 using namespace std

SP1716 GSS3 - Can you answer these queries III 线段树

题目传送门:SP1043 GSS1 - Can you answer these queries I 更好的阅读体验 动态维护子段和最大值 前置知识 静态维护子段和最大值:SP1043 GSS1 - Can you answer these queries I 题解传送 题解: 提供结构体指针线段树写法: 设\(l\)为区间左端点, \(r\)为区间右端点: \(ls\)为以\(l\)为左端点的最大子段和, \(rs\)为以\(r\)为右端点的最大子段和; \(sum\)为区间和, \(val\

SP1716 GSS3 - Can you answer these queries III - 动态dp,线段树

GSS3 Description 动态维护最大子段和,支持单点修改. Solution 设 \(f[i]\) 表示以 \(i\) 为结尾的最大子段和, \(g[i]\) 表示 \(1 \sim i\) 的最大子段和,那么 \[f[i] = max(f[i - 1] + a[i], a[i])\] \[g[i] = max(g[i - 1], f[i])\] 发现只跟前一项有关.我们希望使用矩阵乘法的思路,但是矩阵乘法通常只能适用于递推问题.因此我们引入广义矩阵乘法. 矩阵乘法问题可分治的原因在于

SP1716 GSS3 - Can you answer these queries III

题意:给定n个数a[1]~a[n],有q次操作. 操作 0 x y:把第a[x]修改为y: 操作 1 x y:询问x到y的的最大子段和. 输入:第一行:一个正整数n,表示有n个整数: 第二行:n个整数,表示数列: 第三行:一个正整数q,表示有q个询问: 第4~q+3行:每行三个数p,x,y,表示三种操作. 输出:对于每一个种类为1的询问,输出最大子段和. 输入样例: 41 2 3 441 1 30 3 -31 2 41 3 3 输出样例: 64-3 解析:用线段树进行维护,记录下每一段的和(su

模板——线段树维护最大子段和 SP1716 GSS3 - Can you answer these queries III

${\color{Pink}{>>Question}}$ 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #define ll long long 7 using namespace std; 8 9 template <typename T> void in

数据结构(线段树):SPOJ GSS3 - Can you answer these queries III

GSS3 - Can you answer these queries III 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{

SPOJ GSS3 Can you answer these queries III (线段树)

题目大意: 求区间最大子区间的和. 思路分析: 记录左最大,右最大,区间最大. 注意Q_L  和 Q_R  就好. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define lson num<<1,s,mid #define rson num<<1|1,mid+1,e #define maxn 55555 using na

题解 SP1716 【GSS3 - Can you answer these queries III】

\[ Preface \] 没有 Preface. \[ Description \] 维护一个长度为 \(n\) 的数列 \(A\) ,需要支持以下操作: 0 x y 将 \(A_x\) 改为 \(y\) . 1 x y 求 \(\max\limits_{x \leq l \leq r \leq y}{\sum_{i=l}^rA[i]}\) . \[ Solution \] 区间最大子段和 是一个非常经典的问题. 对于 整体最大子段和 来说,一般有 \(O(n)\) 的 贪心 和 分治 做法,

SPOJ GSS3 Can you answer these queries III ——线段树

[题目分析] GSS1的基础上增加修改操作. 同理线段树即可,多写一个函数就好了. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream&