GSS3 - Can you answer these queries III
Posted zzh-brim
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GSS3 - Can you answer these queries III相关的知识,希望对你有一定的参考价值。
题意翻译
nnn 个数, qqq 次操作
操作0 x y
把 AxA_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.
输入输出样例
4 1 2 3 4 4 1 1 3 0 3 -3 1 2 4 1 3 3
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\n", ans); } } return 0; }
以上是关于GSS3 - Can you answer these queries III的主要内容,如果未能解决你的问题,请参考以下文章
GSS3 - Can you answer these queries III
SP1716 GSS3 - Can you answer these queries III
SP1716 GSS3 - Can you answer these queries III
SPOJ GSS3 Can you answer these queries III ——线段树