BJOI2016 Sushi

tema Enlace

Descripción

Dada una longitud \ (N \) secuencia \ (A \) , y un intervalo \ ([L, R & lt] \) .

¿Cuántos pesos contigua subsecuencia de la suma en el intervalo, es decir, satisface \ (1 \ le i \ le j \ le n \) y satisface \ (L \ le \ sum_ { k = i} ^ {j} a [i ] \ le r \) esquema de número.

Solución

Gama y es fácil pensar en el uso de prefijos y de conversión, de manera que la sección correspondiente en dos puntos. Conjunto \ (s) \ es \ (a \) prefijo y luego las estadísticas se constituirán como tales.

Estadísticas \ (0 \ le i <j \ le n \) satisface (L \ le s [j] - s [i] \ le R \) \ número de programas. Sólo un juego de interrogación de datos, al parecer para apoyar a enumerar unidimensional, tal vez desee enumerar \ (S [i] \) , entonces transformado lo fórmula es satisfacer \ (L + s [i] \ le s [j] \ le R + s [i] \) y (<\) \ i j un \ (J \) número.

Esto es obviamente un orden parcial de los problemas bidimensionales, la práctica es:

  • enumeración inversa \ (i \)
  • Las consultas de respuesta
  • Insertar \ (s [i] \)

Modificar monótona, consulta el rango de operación de nuestra demasiado familiar. Pero esta información como rango discreto no va a hacer, no es árbol segmento de la prescripción discreta, única dinámica. (Más tarde, pensé por un momento parecen ser puesto en la matriz de valores discretos todo alrededor, por lo que escribir dos versiones).

complejidad del tiempo

\ (O (n \ log_2 10 ^ {10}) \)

Código

Dinámica de prescripción edición árbol segmento

#include <iostream>
#include <cstdio>

using namespace std;

typedef long long LL;

const int N = 100005;

int n, L, R, rt, idx;

struct T{
	int l, r, v;
} t[N * 30];

LL Lt = 9e18, Rt = -9e18;

LL s[N], ans = 0;

void inline pushup(int p) {
	t[p].v = t[t[p].l].v + t[t[p].r].v;
}

void insert(int &p, LL l, LL r, LL x) {
	if (!p) p = ++idx;
	t[p].v++;
	if (l == r) return;
	LL mid = (l + r) >> 1;
	if (x <= mid) insert(t[p].l, l, mid, x);
	else insert(t[p].r, mid + 1, r, x);
}

int query(int p, LL l, LL r, LL x, LL y) {
	if (!p) return 0;
	if (x <= l && r <= y) return t[p].v;
	LL mid = (l + r) >> 1, res = 0;
	if (x <= mid) res += query(t[p].l, l, mid, x, y);
	if (mid < y) res += query(t[p].r, mid + 1, r, x, y);
	return res;
}

int main() {
	scanf("%d%d%d", &n, &L, &R);
	for (int i = 1; i <= n; i++) scanf("%lld", &s[i]), s[i] += s[i - 1];
	for (int i = 1; i <= n; i++) {
		Lt = min(Lt, s[i]);
		Rt = max(Rt, R + s[i]);
	}
	for (int i = n; ~i; i--) {
		ans += query(rt, Lt, Rt, L + s[i], R + s[i]);
		if (i) insert(rt, Lt, Rt, s[i]);
	}
	printf("%lld\n", ans);
	return 0;
}

edición árbol Fenwick

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long LL;

const int N = 100005;

int n, L, R, tot, c[N];

LL s[N], d[N], ans = 0;

int inline get(LL x) {
	return lower_bound(d + 1, d + 1 + tot, x) - d;
}

void inline add(int x) {
	for (; x <= tot; x += x & -x) c[x]++;
}

int inline ask(int x) {
	int res = 0;
	for (; x; x -= x & -x) res += c[x];
	return res;
}

int main() {
	scanf("%d%d%d", &n, &L, &R);
	for (int i = 1; i <= n; i++) 
		scanf("%lld", &s[i]), s[i] += s[i - 1], d[++tot] = s[i];
	sort(d + 1, d + 1 + tot);
	tot = unique(d + 1, d + 1 + tot) - d - 1;
	for (int i = n; ~i; i--) {
		int A = lower_bound(d + 1, d + 1 + tot, L + s[i]) - d - 1; 
		int B = upper_bound(d + 1, d + 1 + tot, R + s[i]) - d - 1; 
		ans += ask(B) - ask(A);
		if (i) add(get(s[i]));
	}
	printf("%lld\n", ans);
	return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/dmoransky/p/12602313.html
Recomendado
Clasificación