[Ybt Advanced 4-4-3] [luogu P4513] Xiaobai visita el parque

Xiaobai visita el parque

Enlace de tema: ybt high -fficiency advanced 4-4-3 / luogu P4513

Idea general

Para darle una secuencia, hay dos operaciones que mantener.
Modificación de un solo punto y encontrar el peso del subintervalo con el mayor peso en un intervalo.

Ideas

De hecho, este es un enfoque de árbol de segmento de línea muy clásico.

Con solo buscar este intervalo, se puede dividir en un punto de división para encontrar el sufijo más grande en el frente y el sufijo más grande en la parte posterior, juntos, puede ser el más grande en este intervalo. (De lo contrario, debe ser el valor del intervalo separado por su punto de división)

Luego, pensará en usar el árbol de segmento de línea para mantener el sufijo de prefijo máximo y el peso total, y luego, a través de estas tres cosas, puede mantener el peso de subintervalo máximo.

Luego, al calcular la respuesta, si están en el mismo lado del punto de división, es fácil de decir, pero si no están en el mismo lado, debe averiguar los valores mantenidos arriba a la izquierda y a la derecha. lados y luego fusionarlos.
Debido a que los valores en estos dos lados pueden no estar en el árbol del segmento de línea, es mejor que su función devuelva la estructura de estos valores relacionados (para que sea conveniente y fácil de hacer).

Código

#include<cstdio>
#include<algorithm>
#define ll long long

using namespace std;

struct node {
    
    
	ll x, lazy, lsum, rsum, sum;
}tree[4000001];
int n, m, a[500001];
int op, x, y;

void up(int now) {
    
    
	tree[now].x = tree[now << 1].x + tree[now << 1 | 1].x;
	tree[now].lsum = max(tree[now << 1].lsum, tree[now << 1].x + tree[now << 1 | 1].lsum);
	tree[now].rsum = max(tree[now << 1 | 1].rsum, tree[now << 1 | 1].x + tree[now << 1].rsum);
	tree[now].sum = max(max(tree[now << 1].sum, tree[now << 1 | 1].sum), tree[now << 1].rsum + tree[now << 1 | 1].lsum);
}

void build(int now, int l, int r) {
    
    
	if (l == r) {
    
    
		tree[now].x = a[l];
		tree[now].lsum = tree[now].rsum = tree[now].sum = a[l];
		return ;
	}
	
	int mid = (l + r) >> 1;
	build(now << 1, l, mid);
	build(now << 1 | 1, mid + 1, r);
	
	up(now);
}

node get_sum(int now, int l, int r, int L, int R) {
    
    
	if (L <= l && r <= R) {
    
    
		return tree[now];
	}
	
	int mid = (l + r) >> 1;
	node re;
	//只存在于一遍
	if (R <= mid) return get_sum(now << 1, l, mid, L, R);
	if (mid + 1 <= L) return get_sum(now << 1 | 1, mid + 1, r, L, R);
	
	//两边都有,就要想 up 一样比较
	node re1= get_sum(now << 1, l, mid, L, R);
	node re2 = get_sum(now << 1 | 1, mid + 1, r, L, R);
	
	re.x = re1.x + re2.x;
	re.lsum = max(re1.lsum, re1.x + re2.lsum);
	re.rsum = max(re2.rsum, re2.x + re1.rsum);
	re.sum = max(max(re1.sum, re2.sum), re1.rsum + re2.lsum);
	return re;
}

void change_num(int now, int l, int r, int pl, int ch_num) {
    
    
	if (l == r) {
    
    
		tree[now].x = ch_num;
		tree[now].lsum = tree[now].rsum = tree[now].sum = ch_num;
		return ;
	}
	
	int mid = (l + r) >> 1;
	if (pl <= mid) change_num(now << 1, l, mid, pl, ch_num);
		else change_num(now << 1 | 1, mid + 1, r, pl ,ch_num);
	
	up(now);
}

int main() {
    
    
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	
	build(1, 1, n);
	
	while (m--) {
    
    
		scanf("%d %d %d", &op, &x, &y);
		
		if (op == 1) {
    
    
			if (x > y) swap(x, y);
			printf("%lld\n", get_sum(1, 1, n, x, y).sum);
		}
		else change_num(1, 1, n, x, y);
	}
	
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_43346722/article/details/115275199
Recomendado
Clasificación