zoukankan      html  css  js  c++  java
  • 题解【SP1716】GSS3

    题目描述

    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{A_i + A_{i+1} + .. + A_j) (|) (x<=i<=j<=y }).

    输入输出格式

    输入格式

    The first line of input contains an integer (N).

    The following line contains (N) integers, representing the sequence (A_{1}..A_{N}).

    The third line contains an integer (M). The next (M) lines contain the operations in following form:

    0 x y: modify (A_x) into (y) ((|y|<=10000)).

    1 x y: print (max{A_i + A_{i+1} + .. + A_j) (|) (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
    

    题意翻译

    (n) 个数,(q) 次操作

    操作0 x y(A_x) 修改为(y)

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

    题解

    这题就是GSS1的带修改版本,建议先看一看我的题解,了解不带修改的版本怎么写。

    本题的代码基于我GSS1的题解,一些注释也可以在那里看到。

    这里讲一讲怎么修改:

    与线段树相似,如果当前已经访问到了叶子节点,就直接将这个节点的所有参数都设为要修改的值即可,否则就递归左子树或右子树。最后记得上传节点!

    下面给出(AC)代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    
    using namespace std;
    
    inline int gi()
    {
        int f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar();}
        return f * x;
    }
    
    int n, m;
    struct Node
    {
    	int sum, lans, rans, ans;
    } t[50005 << 2];
    
    inline void pushup(int x)
    {
    	t[x].sum = t[x << 1].sum + t[(x << 1) | 1].sum;
    	t[x].lans = max(t[x << 1].lans, t[x << 1].sum + t[(x << 1) | 1].lans);
    	t[x].rans = max(t[(x << 1) | 1].rans, t[(x << 1) | 1].sum + t[x << 1].rans);
    	t[x].ans = max(max(t[x << 1].ans, t[(x << 1) | 1].ans), t[x << 1].rans + t[(x << 1) | 1].lans);
    }
    
    void bulid(int s, int o, int p)
    {
    	if (s == o)
    	{
    		t[p].sum = t[p].lans = t[p].rans = t[p].ans = gi();
    		return;
    	}
    	int mid = (s + o) >> 1;
    	bulid(s, mid, p << 1);
    	bulid(mid + 1, o, (p << 1) | 1);
    	pushup(p);
    }
    
    void modify(int l, int r, int s, int o, int p)//修改操作
    {
    	if (s == o)//已经是叶子节点了
    	{
    		t[p].ans = t[p].lans = t[p].rans = t[p].sum = r;//就更新它的所有参数
    		return;
    	}
    	int mid = (s + o) >> 1;//找中点
    	if (l <= mid) modify(l, r, s, mid, p << 1);//点在中点左边就递归左子树
    	else modify(l, r, mid + 1, o, (p << 1) | 1);//否则递归右子树
    	pushup(p);//上传节点
    }
    
    Node getans(int l, int r, int s, int o, int p)
    {
    	if (l <= s && r >= o)
    	{
    		return t[p];
    	}
    	int mid = (s + o) >> 1;
    	if (l > mid) return getans(l, r, mid + 1, o, (p << 1) | 1);
    	if (r <= mid) return getans(l, r, s, mid, p << 1);
    	else 
    	{
    		Node ans, a, b;
    		a = getans(l, r, s, mid, p << 1), b = getans(l, r, mid + 1, o, (p << 1) | 1);
    		ans.sum = a.sum + b.sum;
    		ans.ans = max(max(a.ans, a.rans + b.lans), b.ans);
    		ans.lans = max(a.lans, a.sum + b.lans);
    		ans.rans = max(b.rans, b.sum + a.rans);
    		return ans;
    	}
    }
    
    int main()
    {
    	n = gi();
    	bulid(1, n, 1);
    	m = gi();
    	for (int i = 1; i <= m; i++)
    	{
    		int fl = gi(), x = gi(), y = gi();
    		if (fl == 1) printf("%d
    ", getans(x, y, 1, n, 1).ans);//如果是要求答案就输出答案
    		else modify(x, y, 1, n, 1);//否则就进行修改
    	}
    	return 0;
    }
    
  • 相关阅读:
    【转】大内高手—内存管理器
    [转]内存泄漏测试小工具 LeakDiag
    [转]内存泄漏测试小工具 LeakDiag
    (转)SplitContainer 控件(Windows 窗体)
    (转)c++内存分配优先使用内存池,而不是new,delete
    (转)C++内存池
    LeakDiag 使用注意
    Struts Validator验证器使用指南
    oracle JOB样例
    oralce杀session
  • 原文地址:https://www.cnblogs.com/xsl19/p/11131118.html
Copyright © 2011-2022 走看看