杭电1166--敌兵布阵(线段树 | 树状数组)

给一些数, 有几个操作,求区间内数的和,修改区间内某个位置的值,---- > 区间求(修改)和。
线段树:
#include <cstdio>
#include <cstring>
#include <iostream>
#define max(a, b) a>b?a:b
const int MAXN = 50050;
using namespace std;
struct Node
{
    int left, right, sum;
} tree[MAXN*3];
int n, num[MAXN];
void Build(int root, int left, int right)
{
    tree[root].left = left;
    tree[root].right = right;
    if(left == right)
    {
        tree[root].sum = num[left];
        return;        
    }
    int mid = (left+right)>>1;
    Build(root<<1, left, mid);
    Build(root<<1|1, mid+1, right);  //
    tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;
}
void Update(int root, int pos, int val)
{
    if(tree[root].left == tree[root].right)
    {
        tree[root].sum += val; return; 
    } 
    int mid = (tree[root].left + tree[root].right) >> 1;
    if(pos <= mid)
        Update(root<<1, pos, val);
    else
        Update(root<<1|1, pos, val);
    tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;
} 


int Query(int root, int left, int right)
{
    if(left == tree[root].left && right == tree[root].right)
        return tree[root].sum;
    int mid = (tree[root].left + tree[root].right) >> 1;
    if(right <= mid)
        return     Query(root<<1, left, right);
    else if(left > mid)
        return Query(root<<1|1, left, right);
    else
        return Query(root<<1, left, mid) + Query(root<<1|1, mid+1, right); 
    
}
int main()
{
    int t, temp = 1;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)    
            scanf("%d", &num[i]);
        Build(1, 1, n);
        printf("Case %d:
", temp++);
        char str[20]; int a, b;
        while(~scanf("%s", str))
        {
            if(str[0] == 'E')
                break;
            scanf("%d %d", &a, &b);
            if(str[0] == 'Q')
                printf("%d
", Query(1, a, b));
            if(str[0] == 'S')
                Update(1, a, -b);
            if(str[0] == 'A')
                Update(1, a, b);
        }
    }
    return 0;
}

树状数组:


函数Odd()求的是: 为pos在二进制下末尾0的个数;

http://blog.csdn.net/cambridgeacm/article/details/7771782#
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n, a[50005];
int Odd(int src)
{
    return src & (src^(src-1));
}
void Update(int pos, int val)
{
    while(pos <= n)
    {
        a[pos] += val;
        pos += Odd(pos);
    }
}
int Getsum(int pos)
{
    int sum = 0;
    while(pos > 0)
    {
        sum += a[pos];
        pos -= Odd(pos);    
    }
    return sum;
}
int main()
{
    int t;
    scanf("%d", &t);
    for(int Q = 1; Q <= t; Q++)
    {
        memset(a, 0, sizeof(a));
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
        {
            int num;
            scanf("%d", &num);
            Update(i, num);
        }
        printf("Case %d:
", Q);
        char str[10];
        while(scanf("%s", str), str[0] != 'E')
        {
            int a, b;
            scanf("%d %d", &a, &b);
            if(str[0] == 'A')
                Update(a, b);
            else if(str[0] == 'S')
                Update(a, -b);
            else //if(str[0] == 'Q');
                printf("%d
", Getsum(b) - Getsum(a-1));
        }
    }
    return 0;    
}

 New code:

#include <cstdio>
#include <cstring>
#define N 50001
int n, num[N];
struct Node{
    int sum, left, right;
}tree[N*3];
int Build(int root, int left, int right){
    tree[root].left = left;
    tree[root].right = right;
    if(left == right)
        return tree[root].sum = num[left];
    int mid = (left+right) / 2;
    Build(root<<1, left, mid);
    Build(root<<1|1, mid+1, right);
    tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;  
}
int Update(int root, int pos, int val){
    if(tree[root].left == tree[root].right)
        return tree[root].sum += val; 
    int mid = (tree[root].left+tree[root].right) / 2;
    if(pos  <= mid)
        Update(root<<1, pos, val);
    else
        Update(root<<1|1, pos, val);
    tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum; 
} 
int Query(int root, int left, int right){
    if(left == tree[root].left && right == tree[root].right)
        return tree[root].sum;
    int mid = (tree[root].left + tree[root].right) / 2;
    if(right <= mid)
        return Query(root<<1, left, right);
    else if(left > mid)
        return Query(root<<1|1, left, right);
    else
        return Query(root<<1, left, mid) + Query(root<<1|1, mid+1, right);
}
int main(){
    int t, tem = 1;
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
            scanf("%d", &num[i]);
        Build(1, 1, n);
        printf("Case %d:
", tem++); char str[10];
        while(scanf("%s", str) != EOF){
            if(str[0] == 'E')
                break; 
            int a, b;
            scanf("%d%d", &a, &b);
            if(str[0] == 'Q')
                printf("%d
", Query(1, a, b));
            if(str[0] == 'A')
                Update(1, a, b);
            if(str[0] == 'S')    
                Update(1, a, -b);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/soTired/p/4754470.html