标签:UI iii mod lag can gis get 最大子段和 输入格式
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
标签:UI iii mod lag can gis get 最大子段和 输入格式
原文地址:https://www.cnblogs.com/zZh-Brim/p/9112431.html