¿Qué es una matriz de árbol? Hablando de la matriz de árboles (1)

Matriz de árbol

Si tiene alguna pregunta, ¡hable en la sección de comentarios!

Introducción al problema

Enlace del título: HDU1166

n números, m operaciones.
Las operaciones son:

  1. Consulta ij (suma del intervalo de consulta [i, j])
  2. Sumar ij (aumentar j para el i-ésimo dígito)
  3. Sub ij (el número i-ésimo menos j)

Usar matriz de árbol

Para resolver este problema de manera simple y eficiente, necesitamos usar una matriz de árbol (por supuesto, también se puede usar un árbol de segmento de línea).
Portal de árbol de segmento de línea : árbol de segmento de línea
Entonces , ¿qué es una matriz de árbol? La matriz del árbol de simulación es una matriz de árbol ~ se mantiene la suma del prefijo.

como muestra la imagen.
Inserte la descripción de la imagen aquí

Variables requeridas

Para la siguiente introducción, primero presentamos las variables requeridas.

int tree[N], a[N];
// tree[N]: 树状数组
// a[N]   : 原数组

lowbit

Podemos (bu) y (neng) encontrar que la matriz de figuras anterior satisface las siguientes reglas:

árbol [1] = un [1] árbol [1] = un [1] t r e e [ 1 ]=un [ 1 ]
árbol [2] = un [1] + un [2] árbol [2] = a [1] + a [2]t r e e [ 2 ]=a [ 1 ]+un [ 2 ]
árbol [3] = un [3] árbol [3] = un [3]t r e e [ 3 ]=a [ 3 ]
árbol [4] = a [1] + a [2] + a [3] + a [4] árbol [4] = a [1] + a [2] + a [3] + a [ 4]t r e e [ 4 ]=a [ 1 ]+a [ 2 ]+a [ 3 ]+a [ 4 ]

规律 如下 :
árbol [i] = a [i - 2 k + 1] + a [i - 2 k + 2] +. . . + un árbol [i] [i] = a [i - 2 ^ k + 1] + a [i - 2 ^ k + 2] + ... + a [i]t r e e [ i ]=un [ yo-2k+1 ]+un [ yo-2k+2 ]+. . .+a [ i ]
dondekkk moneda yiisoy binarioDe menor a mayorLa longitud de ceros consecutivos.

por ejemplo:

Decimal Binario k
4 4 4 100 100 1 0 0 2 2 2

Por lo tanto, de la regla anterior, podemos obtener: árbol [4] = a [1] + a [2] + a [3] + a [4] árbol [4] = a [1] + a [2] + a [3] + a [4]t r e e [ 4 ]=a [ 1 ]+a [ 2 ]+a [ 3 ]+a [ 4 ] .

Lo que hace la matriz de árbol es simular esta regla y almacenar la suma del prefijo en la matriz de esta manera.

lograr

lowbit

// 比较简单的一个函数,是树状数组的灵魂所在
int lowbit(int x) {
	// 返回x与上x的二进制中从右向左数第一位1变为0后的数字。
	return x & (-x);
}

añadir

// 数组下标为 x 的元素增加 k
void add(int x, int k) {
	// 不仅需要tree[x]增加k,也需要所有包含x的tree增加k
	while (x <= n) {
		tree[x] += k;
		// 遍历寻找所有包含x的区间
		x += lowbit(x);
	}
}

consulta

// 查询区间 [1, x] 的和
int query(int x) {
	int ans = 0;
	// 如上面的图中所示,树状数组中的tree[x]很可能并非[1, x]的区间和,而只是[1, x]的子区间的区间和
	while (x > 1) {
		ans += tree[x];
		// 遍历其它子区间
		x -= lowbit(x);
	}
}

Código completo

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>

using namespace std;
//#pragma GCC optimize(2)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define ull unsigned long long
#define ll long long
#define rep(i, x, y) for(int i=x;i<=y;i++)
#define mms(x, n) memset(x, n, sizeof(x))
#define mmc(A, tree) memcpy(A, tree, sizeof(tree))
#define INF (0x3f3f3f3f)
#define mod (ull)(1e9+7)
typedef pair<int, int> P;
const int N = 1e5 + 10;
int n;
int tree[N], a[N];
char ch[10];

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

void add(int x, int k) {
    while (x <= n) {
        tree[x] += k;
        x += lowbit(x);
    }
}

int query(int x) {
    int ans = 0;
    while (x >= 1) {
        ans += tree[x];
        x -= lowbit(x);
    }
    return ans;
}

int main() {
//    freopen("input.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    for (int _ = 1; _ <= T; _++) {
        mms(tree, 0);
        mms(a, 0);
        printf("Case %d:\n", _);
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            add(i, a[i]);
        }
        int c, d;
        while (scanf("%s", ch) && ch[0] != 'E') {
            scanf("%d%d", &c, &d);
            if (ch[0] == 'A') {
                add(c, d);
            } else if (ch[0] == 'S') {
                add(c, -d);
            } else if (ch[0] == 'Q') {
                int ans = query(d) - query(c - 1);
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}

Supongo que te gusta

Origin blog.csdn.net/qq_45934120/article/details/108037724
Recomendado
Clasificación