题意:含n个元素的序列 ,有q个操作。
操作( p x y)有三种:
0 x y :把第x个的值改为y
1 x y:交换第x个和第y个的值
2 x y:问区间[x,y]里面连续k个的子序列的最大和
思路:先处理序列,SumK[i]表示从i开始的k个数的和,然后线段树建树,成段更新,查询。更新只要处理成对区间最值得加减就可以了。
成段更新还是不熟悉,于是顺便做了 POJ - 3468 A Simple Problem with Integers,也是成段更新,查询为区间元素和,有些不同。
#include <iostream> #include <cstdio> using namespace std; #define max(a,b) a>b?a:b const int MAXN = 200000 + 1000; int num[MAXN]; int sumK[MAXN]; int sum[MAXN]; int father[MAXN]; struct node { int l, r; int Max; int lazy; }tree[MAXN*3]; inline void pushUp(int i) { int ls = i << 1, rs = ls + 1; tree[i].Max = max(tree[ls].Max, tree[rs].Max); } void pushDown(int i) { if (tree[i].lazy) { int ls = i << 1, rs = ls + 1; tree[ls].lazy += tree[i].lazy; tree[rs].lazy += tree[i].lazy; tree[ls].Max += tree[i].lazy; tree[rs].Max += tree[i].lazy; tree[i].lazy = 0; } } void build(int l, int r, int i) { tree[i].lazy = 0; tree[i].l = l; tree[i].r = r; if (l == r) { tree[i].Max = sumK[l]; father[l] = i; return; } int ls = i << 1, rs = ls + 1; int m = (l + r) >> 1; build(l, m, ls); build(m + 1, r, rs); pushUp(i); } void update(int l, int r, int i, int v) { if (l <= tree[i].l && r >= tree[i].r) { tree[i].lazy += v; tree[i].Max += v; return; } pushDown(i); int m = (tree[i].l + tree[i].r) >> 1, ls = i << 1, rs = ls + 1; if (r <= m) update(l, r, ls, v); else if (l > m) update(l, r , rs, v); else { update(l, m, ls, v); update(m + 1, r, rs, v); } pushUp(i); } int query(int l, int r, int i) { if (l<=tree[i].l && r>=tree[i].r) return tree[i].Max; pushDown(i); int m = (tree[i].l + tree[i].r) >> 1, ls = i << 1, rs = ls + 1; if (r <= m) return query(l, r, ls); else if (l > m) return query(l, r, rs); else return max(query(l, m, ls), query(m + 1, r, rs)); } int main() { int casen; scanf("%d", &casen); while (casen--) { int n, m, k; scanf("%d%d%d", &n, &m, &k); for (int i = 1; i <= n; i++) scanf("%d", &num[i]); int len = n - k + 1; sum[0] = 0; for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + num[i]; for (int i = 1; i <= len; i++) sumK[i] = sum[i + k - 1] - sum[i - 1]; build(1, len, 1); int op, x, y; while (m--) { scanf("%d%d%d", &op, &x, &y); if (op == 0) { int add = y - num[x]; num[x] = y; int s = max(x - k + 1, 1); int e = x; update(s, e, 1, add); } else if (op == 1) { int add1 = num[x] - num[y]; int add2 = num[y] - num[x]; int s1 = max(x - k + 1, 1); int s2 = max(y - k + 1, 1); int e1 = x; int e2 = y; int temp = num[x]; num[x] = num[y]; num[y] = temp; update(s1, e1, 1, add2); update(s2, e2, 1, add1); } else { int s = x; int e = max(y - k + 1, 1); int ans = query(s, e, 1); printf("%d\n", ans); } } } }