线段树
来源:互联网 发布:linux怎么查看ntp进程 编辑:程序博客网 时间:2024/06/01 09:03
线段树(1):点修改
动态范围最大、最小、求和问题。给出一个有n个元素的数组A1,A2,A3,···An,设计一种数据结构,支持以下两种操作。
□Update(x, v):把Ax修改为v。
□Query(L, R):计算区间{ A[L],A[L + 1],A[L + 2],···,A[R - 1],A[R] }的和、最大值,最小值。
HDU 1166
#include <stdio.h>const int MAXN = 50005;int sum[MAXN << 2];void pushup(int rt){sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];}void build(int L, int R, int rt){if (L == R){scanf("%d", &sum[rt]);return ;}int M = L + (R - L) / 2;build(L, M, rt << 1);build(M + 1, R, rt << 1 | 1);pushup(rt);}void update(int p, int add, int L, int R, int rt){if (L == R){sum[rt] += add;return ;}int M = L + (R - L) / 2;if (p <= M){update(p, add, L, M, rt << 1);}else{update(p, add, M + 1, R, rt << 1 | 1);}pushup(rt);}int query(int qL, int qR, int L, int R, int rt){if (qL <= L && qR >= R){return sum[rt];}int ans = 0;int M = L + (R - L) / 2;if (qL <= M){ans += query(qL, qR, L, M, rt << 1);}if (M < qR){ans += query(qL, qR, M + 1, R, rt << 1 | 1);}return ans;}int main(){int n, T;scanf("%d", &T);for (int ca = 1; ca <= T; ca++){printf("Case %d:\n", ca);scanf("%d", &n);build(1, n, 1);char op[8];while (scanf("%s", op) && op[0] != 'E'){int a, b;scanf("%d%d", &a, &b);if (op[0] == 'Q'){printf("%d\n", query(a, b, 1, n, 1));}else if (op[0]== 'A'){update(a, b, 1, n, 1);}else{update(a, - b, 1, n, 1);}}}return 0;
线段树(2):区间修改
动态范围最大、最小、求和问题。给出一个有n个元素的数组A1,A2,A3,···An,设计一种数据结构,支持以下两种操作。
□Add(L, R, v):把A[L],A[L + 1],A[L + 2],A[R - 1],A[R]全部增加v。
□Query(L, R):计算区间{ A[L],A[L + 1],A[L + 2],···,A[R - 1],A[R] }的和、最大值,最小值。POJ 3468
<pre name="code" class="cpp">#include <stdio.h>const int MAXN = 111111;long long sum[MAXN<<2];long long add[MAXN<<2];void pushup(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1 | 1];}void pushdown(int rt, int m){ if (add[rt]) { add[rt << 1] += add[rt]; add[rt << 1 | 1] += add[rt]; sum[rt << 1] += (m - (m >> 1)) * add[rt]; sum[rt << 1 | 1] += (m >> 1) * add[rt]; add[rt] = 0; }}void build(int L, int R, int rt){ add[rt] = 0; if (L == R) { scanf("%lld", &sum[rt]); return ; } int M = L + (R - L) / 2; build(L, M, rt << 1); build(M + 1, R, rt << 1 | 1); pushup(rt);}void update(int a, int b, int c, int L, int R, int rt){ if (a <= L && R <= b) { add[rt] += c; sum[rt] += (long long)c * (R - L + 1); return ; } pushdown(rt, R - L + 1); int M = L + (R - L) / 2; if (a <= M) update(a, b, c, L, M, rt << 1); if (b > M) update(a, b, c, M + 1, R, rt << 1 | 1); pushup(rt);}long long query(int x, int y, int L, int R, int rt){ if (x <= L && R <= y) { return sum[rt]; } pushdown(rt, R - L + 1); int M = L + (R - L) / 2; long long ans = 0; if (x <= M) ans += query(x, y, L, M, rt << 1); if (y > M) ans += query(x, y, M + 1, R, rt << 1 | 1); return ans;}int main(){ int n, m; scanf("%d%d", &n, &m); build(1, n, 1); while (m--) { getchar(); char ch; int a, b, c; scanf("%c", &ch); if (ch == 'Q') { scanf("%d%d", &a, &b); // printf("___%c___%d____%d\n", ch, a, b); printf("%lld\n", query(a, b, 1, n, 1)); } else { scanf("%d%d%d", &a, &b, &c); // printf("___%c___%d___%d___%d\n", ch, a, b, c); update(a, b, c, 1, n, 1); } } return 0;}
线段树(3):区间修改
动态范围最大、最小、求和问题。给出一个有n个元素的数组A1,A2,A3,···An,设计一种数据结构,支持以下两种操作。
□Set(L, R, v):把A[L],A[L + 1],A[L + 2],A[R - 1],A[R]全部修改为v(v >= 0)。
□Query(L, R):计算区间{ A[L],A[L + 1],A[L + 2],···,A[R - 1],A[R] }的和、最大值,最小值。
HDU 1698
#include <stdio.h>#include <string.h>const int MAXN = 100010;int sum[MAXN<<2];int set[MAXN<<2];void pushup(int rt){sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];}void pushdown(int rt, int x){if (set[rt] != -1){set[rt << 1] = set[rt << 1 | 1] = set[rt];sum[rt << 1] = (x - (x >> 1)) * set[rt];sum[rt << 1 | 1] = (x >> 1) * set[rt];set[rt] = -1;}}void build(int L, int R, int rt){set[rt] = -1; sum[rt] = 1;if (L == R)return ;int M = L + (R - L) / 2;build(L, M, rt << 1);build(M + 1, R, rt << 1 | 1);pushup(rt);}void update(int x, int y, int z, int L, int R, int rt){if (x <= L && R <= y){set[rt] = z;sum[rt] = z * (R - L + 1);return ;}pushdown(rt, R - L + 1);int M = L + (R - L) / 2;if (x <= M)update(x, y, z, L, M, rt << 1);if(y > M)update(x, y, z, M + 1, R, rt << 1 | 1);pushup(rt);}int main(int argc, char **argv){int T;scanf("%d", &T);for (int t = 1; t <= T; t++){int N, Q, x, y, z;scanf("%d", &N);build(1, N, 1);scanf("%d", &Q);while (Q--){scanf("%d%d%d", &x, &y, &z);update(x, y, z, 1, N, 1);}printf("Case %d: The total value of the hook is %d.\n", t, sum[1]);}return 0;}
0 0
- 线段树?线段树!
- 线段树?线段树!
- 线段_线段树
- 线段_线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- HDU 2054 -- A|B?
- 1005
- C语言实现函数多态性
- unity之关于角色三连击
- HDU 2081 -- 手机短号
- 线段树
- 15个顶级Java多线程面试题及答案
- Java中final关键字
- 如何通过map文件轻松找到崩溃的代码行
- Search Insert Position题解
- MySQL ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
- 怎么删除Xcode的缓存
- memcached 一致性hash算法 - consistent hashing
- HDU 2099 -- 整除的尾数