POJ - 4047 Garden(线段树成段更新,查询最值)

来源:互联网 发布:炼数成金 大数据分析师 编辑:程序博客网 时间:2024/05/22 05:22

题意:含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:bconst 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);elsereturn 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);}}}}


0 0
原创粉丝点击