线段树

来源:互联网 发布: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