Edición mejorada de fruta combinada
Enlace del título: luogu P6033
Idea general
Hay un montón de cosas, cada vez puedes elegir dos cosas y, a costa de su tamaño y suma, combinarlas para obtener una cosa con su tamaño y suma. Luego combínelos en una sola cosa al menor costo.
Igual que de costumbre, pero los datos aumentan, O (nlogn) no puede pasar.
Ideas
La suposición aquí ya es común.
——> No me señales <——
En primer lugar, vemos que los datos son grandes y se utiliza un algoritmo O (n).
Entonces consideramos no usar heap, sino usar algunos otros métodos para mejorar.
Los codiciosos todavía utilizan la codicia anterior.
La pregunta es cómo mantener los dos números más pequeños en una pila de números todo el tiempo.
Luego, consideramos usar un método para ordenar la secuencia original, donde los datos se pueden ordenar por cubos, y si los datos son grandes, también se pueden ordenar por base.
Luego hacemos otra cola y registramos los números recién generados.
Es obvio que los números recién generados deben ser de pequeños a grandes.
Luego elegimos los dos primeros números inferiores de las dos colas (es decir, los cuatro números) cada vez, y luego aparece, inserta un nuevo valor en la cola y registramos el costo.
Entonces hazlo así.
Para abrir mucho tiempo, esto es obvio.
Es obvio comenzar a leer rápido. (Luego me equivoqué durante mucho tiempo porque no lo abrí, así que hice una versión en cola con la mía)
Código
Versión de cola manual
#include<queue>
#include<cstdio>
#define ll long long
using namespace std;
int n;
ll ans, x, y, xx, yy, box[100001];
ll q[10000001], p[10000001], t, tt;
int read() {
int re = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') {
re = re * 10 + c - '0';
c = getchar();
}
return re;
}
int main() {
n = read();
for (int i = 1; i <= n; i++) {
x = 1ll * read();
box[x]++;
}
for (int i = 1; i <= 100000; i++)
for (int j = 1; j <= box[i]; j++) {
q[++q[0]] = i;
}
while (p[0] + q[0] - t - tt > 1) {
x = q[t + 1];
xx = q[t + 2];
y = p[tt + 1];
yy = p[tt + 2];
if (xx < y && t + 2 <= q[0] || (tt + 1 > p[0])) y = xx, t += 2;
else if (yy < x && tt + 2 <= p[0] || (t + 1 > q[0])) x = yy, tt += 2;
else t++, tt++;
ans += x + y;
p[++p[0]] = x + y;
if (p[0] + q[0] - t - tt <= 1) {
break;
}
}
printf("%lld", ans);
return 0;
}
Viene con versión de cola
#include<queue>
#include<cstdio>
#define ll long long
using namespace std;
int n;
ll ans, x, y, xx, yy, box[200001];
queue <ll> q, p;
int read() {
int re = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') {
re = re * 10 + c - '0';
c = getchar();
}
return re;
}
int main() {
n = read();
for (int i = 1; i <= n; i++) {
x = 1ll * read();
box[x]++;
}
for (int i = 1; i <= 200000; i++)
for (int j = 1; j <= box[i]; j++) {
q.push(i);
}
while (1) {
x = 0;
y = 0;
if (q.empty() && p.empty()) break;
if (!q.empty()) xx = q.front();
else {
x = p.front();
p.pop();
if (!p.empty()) {
y = p.front();
p.pop();
}
else break;
}
if (!y) {
if (!p.empty()) yy = p.front();
else {
x = q.front();
q.pop();
if (!q.empty()) {
y = q.front();
q.pop();
}
else break;
}
}
if (!y) {
if (xx < yy) x = xx, q.pop();
else x = yy, p.pop();
if (q.empty() && p.empty()) break;
if (q.empty()) y = p.front(), p.pop();
else if (p.empty()) y = q.front(), q.pop();
else {
xx = p.front();
yy = q.front();
if (xx < yy) y = xx, p.pop();
else y = yy, q.pop();
}
}
ans += x + y;
p.push(x + y);
}
printf("%lld", ans);
return 0;
}