#include <mpi.h>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <algorithm>

using namespace std;

int main(int argc, char** argv) {
    MPI_Init(&argc, &argv);

    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    const int N = 1000; // Tamaño total del vector
    const int local_N = N / size; // Tamaño del fragmento local
    
    vector<double> global_data;
    vector<double> local_data(local_N);

    // El proceso 0 inicializa el vector completo
    if (rank == 0) {
        global_data.resize(N);
        srand(time(NULL));
        for(int i = 0; i < N; i++) {
            global_data[i] = (double)rand() / RAND_MAX * 100.0; // Números entre 0 y 100
        }
        cout << "Vector inicial generado de tamaño " << N << endl;
    }

    // Distribuir los datos entre todos los procesos
    MPI_Scatter(global_data.data(), local_N, MPI_DOUBLE,
                local_data.data(), local_N, MPI_DOUBLE,
                0, MPI_COMM_WORLD);

    // Cada proceso calcula sus estadísticas locales
    double local_max = *max_element(local_data.begin(), local_data.end());
    double local_min = *min_element(local_data.begin(), local_data.end());
    double local_sum = 0;
    for(double val : local_data) {
        local_sum += val;
    }

    // Reducir para obtener las estadísticas globales
    double global_max, global_min, global_sum;
    MPI_Reduce(&local_max, &global_max, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
    MPI_Reduce(&local_min, &global_min, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);
    MPI_Reduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

    // El proceso 0 imprime los resultados
    if (rank == 0) {
        double global_mean = global_sum / N;
        cout << "Estadísticas del vector:" << endl;
        cout << "Máximo: " << global_max << endl;
        cout << "Mínimo: " << global_min << endl;
        cout << "Media: " << global_mean << endl;
    }

    MPI_Finalize();
    return 0;
}