敌兵布阵 HDU

思路:就是树状数组的模板题,利用的就是单点更新和区间求和是树状数组的强项时间复杂度为m*log(n)

没想到自己以前把这道题当线段树的单点更新刷了。

树状数组:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 5e4 + 10;
int tree[maxn], n;
void add(int k, int num)
{
    while (k <= n)
    {
        tree[k] += num;
        k += k&-k;
    }
}
int sum(int k)
{
    int sum = 0;
    while (k)
    {
        sum += tree[k];
        k -= k&-k;
    }
    return sum;
}
int main()
{
    int t, x, y, k=0;
    scanf("%d", &t);
    while (t--)
    {
        memset(tree, 0, sizeof(tree));
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i)
        {
            scanf("%d", &x);        add(i, x);
        }
        char num[20];
        printf("Case %d:
", ++k);
        while (scanf("%s", num), strcmp(num, "End") != 0)
        {
            scanf("%d%d", &x, &y);
            if (strcmp(num,"Add")==0){ add(x, y); }
            else if (strcmp(num,"Sub")==0){ add(x, -y); }
            else{ printf("%d
", sum(y) - sum(x-1)); }
        }
    }
}

线段树

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MID(a,b) (a+((b-a)>>1))
#define MAXN int(1e4)*5+5
struct node
{
    int l, r;
    int sum;
    int mid(){ return MID(l, r); }
};

int num[MAXN], n;

struct Tree
{
    node tree[MAXN << 2];
    void build(int L, int R, int pos)
    {
        tree[pos].l = L;    tree[pos].r = R; //表示区间
        tree[pos].sum = 0;
        if (L == R){tree[pos].sum = num[R]; return; }//到了子叶
        int mid = tree[pos].mid();
        //二分
        build(L, mid, pos<<1);
        build(mid + 1, R, pos << 1 | 1);
        tree[pos].sum = tree[pos << 1].sum + tree[pos << 1 | 1].sum;
    }
    //valu  表示加的值, ind 表示第几个军营。(在区域中的位置)
    void updata(int ind, int pos, int valu)
    {
        if (tree[pos].l == tree[pos].r)
        {
            tree[pos].sum += valu; return;        //叶节点+valu
        }
        int mid = tree[pos].mid();
        //二分查找单点位置?
        if (ind <= mid) updata(ind, pos << 1, valu);
        else updata(ind, pos << 1 | 1, valu);
        tree[pos].sum = tree[pos << 1].sum + tree[pos << 1 | 1].sum;
        //递归,覆盖上一层的sum
    }
    //查询
    int query(int L, int R, int pos)//从根节点查到符合的区间节点
    {
        if (L <= tree[pos].l&&tree[pos].r <= R) return tree[pos].sum;
        int mid = tree[pos].mid();
        int sum1 = 0, sum2 = 0;
        if (L <= mid) sum1 = query(L, R, pos << 1);
        if (R > mid) sum2 = query(L, R, pos << 1 | 1);
        return sum1 + sum2;
    }
};
Tree tree;
int main()
{
    int x, y;
    int t, n,t_case=0;
    scanf("%d", &t);
    while (t--)
    {
        char ch[20];
        scanf("%d", &n);
        printf("Case %d:
", ++t_case);
        for (int i = 1; i <= n; i++)
            scanf("%d", &num[i]);
        tree.build(1, n, 1);
        while (scanf("%s", ch) != EOF)
        {
            if (strcmp(ch, "End") == 0) break;
            else if (strcmp(ch,"Add")==0)
            {
                scanf("%d%d", &x, &y);
                tree.updata(x, 1, y);
            }
            else if (strcmp(ch, "Sub") == 0)
            {
                scanf("%d%d", &x, &y);
                tree.updata(x, 1, -y);
            }
            else if (strcmp(ch, "Query") == 0)
            {
                scanf("%d%d", &x, &y);
                printf("%d
", tree.query(x, y, 1));
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ALINGMAOMAO/p/10079784.html