Permutator
Explicación
Simplificación
Primero, dejemos de lado todo lo raro de los subarreglos y miremos la siguiente simplificación:
Dados dos arreglos y , permutar para minimizar .
Esta versión más simple se resuelve con un enfoque voraz (greedy). Emparejamos el elemento más grande de con el más pequeño de , el segundo más grande de con el segundo más pequeño de , y así sucesivamente hasta haber emparejado todos.
La intuición es que queremos minimizar el impacto que los elementos más grandes de tendrán en la suma, así que los emparejamos con los más pequeños de .
El problema original
Lamentablemente, el problema original no es tan simple.
Sin embargo, nótese que podemos precomputar el número de ocurrencias en las que un índice particular aparecerá entre todas las sumas.
Con esto, si sabemos que aparecerá exactamente veces en la suma, entonces podemos multiplicar de antemano por antes de hacer el emparejamiento de nuestra simplificación.
Si usamos indexación desde cero, cada índice se incluye en posiciones. Esto se debe a que hay posiciones de inicio para subarreglos a la izquierda y posiciones de fin a la derecha.
Luego, podemos multiplicar cada elemento de por su número de ocurrencias para reducir esto a nuestro problema más simple.
Implementación
Complejidad temporal:
#include <algorithm>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
int main() {
int len;
std::cin >> len;
vector<int> a(len);
for (int &i : a) { std::cin >> i; }
vector<int> b(len);
for (int &i : b) { std::cin >> i; }
vector<long long> subarr_num(len);
for (int i = 0; i < len; i++) { subarr_num[i] = (long long)(i + 1) * (len - i); }
vector<long long> actual_a(len);
for (int i = 0; i < len; i++) { actual_a[i] = subarr_num[i] * a[i]; }
std::sort(actual_a.begin(), actual_a.end());
std::sort(b.begin(), b.end(), std::greater<int>());
long long total = 0;
for (int i = 0; i < len; i++) { total += actual_a[i] * b[i]; }
cout << total << endl;
}import java.io.*;
import java.util.*;
public class Permutator {
public static void main(String[] args) throws IOException {
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
int len = Integer.parseInt(read.readLine());
int[] a = Arrays.stream(read.readLine().split(" "))
.mapToInt(Integer::parseInt)
.toArray();
int[] b = Arrays.stream(read.readLine().split(" "))
.mapToInt(Integer::parseInt)
.toArray();
long[] subarrNum = new long[len];
for (int i = 0; i < len; i++) { subarrNum[i] = (long)(i + 1) * (len - i); }
long[] actualA = new long[len];
for (int i = 0; i < len; i++) { actualA[i] = subarrNum[i] * a[i]; }
Arrays.sort(actualA);
Arrays.sort(b);
long total = 0;
for (int i = 0; i < len; i++) { total += actualA[i] * b[len - i - 1]; }
System.out.println(total);
}
}len_ = int(input())
a = [int(i) for i in input().split()]
b = [int(i) for i in input().split()]
subarr_num = [(i + 1) * (len_ - i) for i in range(len_)]
actual_a = [i * j for i, j in zip(subarr_num, a)]
actual_a.sort()
b.sort(reverse=True)
total = sum(i * j for i, j in zip(actual_a, b))
print(total)