hdu 1166 敌兵布阵

        hdu 1166 敌兵布阵

        这是一道树状数组的入门题啦.

        学习树状数组的时候多拿笔算算就比较好理解为什么算法的查询和修改都是logn的了.

        c[i] = a[i - 2^k + 1] + a[i - 2^k + 2] + ... + a[i], 其中k为i的二进制表示最后几位零的个数, 如i=8, 那么1000三个0咯, 那么c[8] = a[1]+a[2]+...+a[8]啦.

        还有哦, i的二进制表示末尾0的个数k还表示了c[i]所包含的范围哦.

        比如吧, c[5], 5的二进制数是101吧, 最后没有0哦, 那么它只能包含a[5]咯, c[6]呢? 6的二进制是110哦, 所以呢, 它能包含a[5]和a[6]哦

        还有呢, i包含的最大的2的幂的因子也能表示i所能包含的个数哦, 如i=5吧, 5没有包含2^x的因子吧, 所以呢, 它只能包含a[5]咯

                      i=4呢. 它有2^2嘛, 所以它能包含4个, i=6, 它只有2^1, 所以它只能包含a[5]和a[6]咯

        所有基数都是没有2的幂的因子吧, 所以基数只能包含一个咯. 即c[1]=a[1], c[3]=a[3]...

#include <stdio.h>
#include <string.h>

#define MAX 50005

int a[MAX];
int c[MAX];
int n;

int lowbit(int index) {
	return index & (-index);
}

int query(int index) {
	int result = 0;
	
	while (index > 0) {
		result += c[index];
		index -= lowbit(index);
	}

	return result;
}

void add(int index, int delta) {
	while (index <= n) {
		c[index] += delta;
		index += lowbit(index);
	}
}

void sub(int index, int delta) {
	while (index <= n) {
		c[index] -= delta;
		index += lowbit(index);
	}
}

int main() {
	int T, t;
	int i, j;
	int lb;
	char q[10];
	int x, y;

	while (scanf("%d", &T) == 1) {
		t = 0;
		while (T--) {
			memset(a, 0, sizeof(a));
			memset(c, 0, sizeof(c));
			scanf("%d", &n);

			for (i = 1; i <= n; i++) {
				scanf("%d", &a[i]);
			}

			for (i = 1; i <= n; i++) {
				lb = lowbit(i);
				for (j = i - lb + 1; j <= i; j++) {
					c[i] += a[j];
				}
			}

			printf("%d", query(5) - query(4));

			t++;
			while (true) {
				scanf("%s", q);
				if (!strcmp(q, "End")) {
					break ;
				}

				scanf("%d%d", &x, &y);
				if (!strcmp(q, "Query")) {
				//	printf("%d\n", query(y) - query(x) + query(x - 1));
					printf("%d\n", query(y) - query(x) + a[x]);
				} else if (!strcmp(q, "Add")) {
					add(x, y);
					a[x] += y;
				} else {
					sub(x, y);
					a[x] -= y;
				}
			}
		}
	}

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值