HDOJ 1166 敌兵布阵(一维树状数组)


http://acm.hdu.edu.cn/showproblem.php?pid=1166


题目是一道很经典的一维树状数组的题,改动一维数组中的一个点,求一段连续区间的和。原理可以去看训练指南,在打代码的时候要回想起那幅经典的图,修改某个值的时候,是向右上角爬,从左子树到父结点,所以是i += lowbit(i)。而查询某一段区间的时候,是向左上角爬,从右子树到父结点,所以是m -= lowbit(m)。

query(i)得到的是[1,i]的和

add(i,d)是给第i个数加上d,sub就是减去d


这道题用iostream会TLE, 还有C字符串中两个字符串的比较要用strcmp。

树状数组开得和普通数组所需要的量一样大就可以。



#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
#define N 50001
#define VN 50001
using namespace std;
int n, a[N], c[VN];
int lowbit(int x)
{
    return x & (-x);
}
int query(int m)
{
    int sum = 0;
    while (m > 0)
    {
        sum += c[m];
        m = m - lowbit(m);
    }
    return sum;
}
void add(int i, int x)
{
    while (i <= n)
    {
        c[i] += x;
        i += lowbit(i);
    }
}
void sub(int i, int x)
{
    while (i <= n)
    {
        c[i] -= x;
        i += lowbit(i);
    }
}
int main()
{
    int T, st, ed, site, ad, sb, cnt = 0;
    char s[20];
    scanf("%d", &T);
    while (T--)
    {
        printf("Case %d:\n", ++cnt); // 注意
        scanf("%d", &n);
        memset(c, 0, sizeof(c));
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            add(i, a[i]);
        }
        while (scanf("%s", s) && strcmp(s, "End") != 0)
        {
            if (strcmp(s, "Query") == 0)
            {
                scanf("%d%d", &st, &ed);
                int ans = query(ed) - query(st - 1);
                printf("%d\n", ans);
            }
            if (strcmp(s, "Add") == 0)
            {
                scanf("%d%d", &site, &ad);
                add(site, ad);
            }
            if (strcmp(s, "Sub") == 0)
            {
                scanf("%d%d", &site, &sb);
                sub(site, sb);
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值