1. 程式人生 > >2017暑假訓練之樹狀陣列

2017暑假訓練之樹狀陣列

單點更新,區間查詢
HDUOJ 1166 敵兵佈陣 420ms
#define lbt(x) x & -x
int a[maxn], n, bit[maxn];

void update(int i, int val) {
	while (i <= n) {
		bit[i] += val;
		i += lbt(i);
	}
}

int sum(int i) {
	int ret = 0;
	while (i) {
		ret += bit[i];
		i -= lbt(i);
	}
	return ret;
}

int query(int l, int r) {
	return sum(r) - sum(l - 1);
}

int main() {
	int T, kase = 1;
	SF(T);
	while (T--) {
		printf("Case %d:\n", kase++);
		SF(n);
		FOR(i, 1, n + 1) bit[i] = 0;
		FOR(i, 1, n + 1) SF(a[i]), update(i, a[i]);
		char op[6];
		int l, r, idx, val;
		while (scanf("%s", op) && strcmp(op, "End")) {
			if (op[0] == 'Q') SFF(l, r), PF(query(l, r));
			else {
				SFF(idx, val);
				if(op[0] == 'S') update(idx, -val);
				else update(idx, val);
			}
		}
	}
	return 0;
}
區間更新,區間查詢

POJ 3468 A Simple Problem with Integers 1000ms

#define lbt(i) i & -i
int n, a[maxn];
LL bit1[maxn], bit2[maxn];

void update(int i, LL val, LL *bit) {
	while (i <= n) {
		bit[i] += val;
		i += lbt(i);
	}
}

LL sum(int i, LL *bit) {
	LL ret = 0;
	while (i) {
		ret += bit[i];
		i -= lbt(i);
	}
	return ret;
}

LL query(int l, int r) {
	LL ret = 0;
	ret += r*sum(r, bit1) - sum(r, bit2);
	ret -= (l - 1) * sum(l - 1, bit1) - sum(l - 1, bit2);
	return ret;
}

int main() {
	int q;
	while (~SFF(n, q)) {
		FOR(i, 1, n + 1) bit1[i] = bit2[i] = 0;
		int b;
		FOR(i, 1, n + 1) {
			SF(a[i]);
			b = a[i] - a[i - 1];
			update(i, b, bit1);
			update(i, (LL)b*(i-1), bit2);
		}
		char op[2];
		int l, r, val;
		while (q--) {
			scanf("%s%d%d", op, &l, &r);
			if (op[0] == 'Q') printf("%lld\n", query(l, r));
			else {
				SF(val);
				update(l, val, bit1);
				update(r + 1, -val, bit1);
				update(l, (LL)val*(l-1), bit2);
				update(r + 1, -(LL)val*r, bit2);
			}
		}
	}
	return 0;
}
區間更新 單點查詢
HDUOJ 1556 Color the ball 811ms
#define lbt(i) i & -i
int n, a[maxn];
int bit[maxn];

void update(int i, int val) {
	while (i <= n) {
		bit[i] += val;
		i += lbt(i);
	}
}
int sum(int i) {
	int ret = 0;
	while (i) {
		ret += bit[i];
		i -= lbt(i);
	}
	return ret;
}

int main() {
	while (SF(n) && n) {
		FOR(i, 1, n + 1) bit[i] = 0;
		int l, r;
		FOR(i, 0, n) {
			SFF(l, r);
			update(l, 1);
			update(r+1, -1);
		}
		bool first = true;
		FOR(i, 1, n + 1) {
			if (first) first = false;
			else putchar(' ');
			printf("%d", sum(i));
		}
		puts("");
	}
	return 0;
}
樹狀陣列求區間最值
HDUOJ 1754 I Hate It 1872ms
運算子優先順序:算數運算子 > 移位運算子 > 關係運算符 > 位運算子 > 條件運算子
#define lbt(i) i & -i
int n, a[maxn], bit[maxn];

void update(int i) {
	while (i <= n) {
		bit[i] = a[i];
		for (int j = 1; j < (lbt(i)); j <<= 1) bit[i] = max(bit[i], bit[i - j]);
		i += lbt(i);
	}
}

int query(int l, int r) {
	int ret = 0;
	if (l <= r) {
		if (r - (lbt(r)) < l) ret = max(query(l, r - 1), a[r]);
		else ret = max(query(l, r - (lbt(r))), bit[r]);
	}
	return ret;
}

int main() {
	//IN(); OUT();
	int q;
	while (~SFF(n, q)) {
		FOR(i, 1, n + 1) bit[i] = 0;
		FOR(i, 1, n + 1) SF(a[i]), update(i);
		char op[2];
		int l, r;
		while (q--) {
			//FOR(i, 1, n + 1) printf("%d ", bit[i]); putchar('\n');
			scanf("%s%d%d", op, &l, &r);
			if (op[0] == 'Q') PF(query(l, r));
			else a[l] = r, update(l);
		}
	}
	return 0;
}
樹狀陣列的本質就是單點更新,區間查詢。