2017暑假訓練之樹狀陣列
阿新 • • 發佈:2019-01-07
單點更新,區間查詢
HDUOJ 1166 敵兵佈陣 420ms
HDUOJ 1556 Color the ball 811ms
HDUOJ 1754 I Hate It 1872ms
運算子優先順序:算數運算子 > 移位運算子 > 關係運算符 > 位運算子 > 條件運算子
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;
}
樹狀陣列的本質就是單點更新,區間查詢。