AtCoder Beginner Contest 391 F

https://atcoder.jp/contests/abc391/tasks/abc391_f

A, B, Cを降順に並べ直すと、 (i, j, k) = (1, 1, 1)と取れば A_iB_j+B_jC_k+C_kA_iが最も大きくなります。その次は、 (i, j, k) = (1, 1, 2), (1, 2, 1), (2, 1, 1)のどれかになります。PriorityQueueを使えば簡単にK番目を求められます。
PriorityQueueに重複してTripletを入れてはいけないのでHashSetを使っています。TripletをHashSetのキーにするには、Hash traitを実装すればよいです。

// K-th Largest Triplet
#![allow(non_snake_case)]

use std::collections::{BinaryHeap, HashSet};
use std::hash::{Hash, Hasher};


//////////////////// library ////////////////////

fn read<T: std::str::FromStr>() -> T {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).ok();
    line.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace()
            .map(|e| e.parse().ok().unwrap()).collect()
}


//////////////////// Triplet ////////////////////

#[derive(Clone, Copy, Eq, PartialEq)]
struct Triplet {
    i: usize,
    j: usize,
    k: usize,
    value: i64
}

impl Ord for Triplet {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.value.cmp(&other.value)
    }
}

impl PartialOrd for Triplet {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl Hash for Triplet {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.i.hash(state);
        self.j.hash(state);
        self.k.hash(state);
    }
}

impl Triplet {
    fn new(i: usize, j: usize, k: usize,
                A: &Vec<i64>, B: &Vec<i64>, C: &Vec<i64>) -> Triplet {
        let value = A[i] * B[j] + B[j] * C[k] + C[k] * A[i];
        Triplet { i, j, k, value }
    }
}


//////////////////// process ////////////////////

fn read_input() -> (usize, Vec<i64>, Vec<i64>, Vec<i64>) {
    let v: Vec<usize> = read_vec();
    let K = v[1];
    let A: Vec<i64> = read_vec();
    let B: Vec<i64> = read_vec();
    let C: Vec<i64> = read_vec();
    (K, A, B, C)
}

fn nexts(t: Triplet, A: &Vec<i64>,
                    B: &Vec<i64>, C: &Vec<i64>) -> Vec<Triplet> {
    let N = A.len();
    let mut ts: Vec<Triplet> = vec![];
    if t.i < N - 1 {
        ts.push(Triplet::new(t.i+1, t.j, t.k, &A, &B, &C))
    }
    if t.j < N - 1 {
        ts.push(Triplet::new(t.i, t.j+1, t.k, &A, &B, &C))
    }
    if t.k < N - 1 {
        ts.push(Triplet::new(t.i, t.j, t.k+1, &A, &B, &C))
    }
    ts
}

fn F(K: usize, mut A: Vec<i64>, mut B: Vec<i64>, mut C: Vec<i64>) -> i64 {
    A.sort_by(|a, b| b.cmp(&a));
    B.sort_by(|a, b| b.cmp(&a));
    C.sort_by(|a, b| b.cmp(&a));
    let mut tree = BinaryHeap::new();
    let t0 = Triplet::new(0, 0, 0, &A, &B, &C);
    tree.push(t0);
    let mut queued = HashSet::new();
    queued.insert(t0);
    for _ in 0..K-1 {
        let t = tree.pop().unwrap();
        for t1 in nexts(t, &A, &B, &C) {
            if !queued.contains(&t1) {
                tree.push(t1);
                queued.insert(t1);
            }
        }
    }
    let t =tree.pop().unwrap();
    t.value
}

fn main() {
    let (K, A, B, C) = read_input();
    println!("{}", F(K, A, B, C))
}