Problem:
Score : 700 points

Problem Statement

There is an integer sequence of length 2^N: A_0, A_1, ..., A_{2^N-1}. (Note that the sequence is 0-indexed.)

For every integer K satisfying 1 \leq K \leq 2^N-1, solve the following problem:

Let i and j be integers. Find the maximum value of A_i + A_j where 0 \leq i < j \leq 2^N-1 and (i or j) \leq K.
Here, or denotes the bitwise OR.

Constraints

1 \leq N \leq 18

1 \leq A_i \leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_0 A_1 ... A_{2^N-1}

Output

Print 2^N-1 lines.
In the i-th line, print the answer of the problem above for K=i.

Sample Input 1

2
1 2 3 1

Sample Output 1

3
4
5

For K=1, the only possible pair of i and j is (i,j)=(0,1), so the answer is A_0+A_1=1+2=3.

For K=2, the possible pairs of i and j are (i,j)=(0,1),(0,2).
When (i,j)=(0,2), A_i+A_j=1+3=4. This is the maximum value, so the answer is 4.

For K=3, the possible pairs of i and j are (i,j)=(0,1),(0,2),(0,3),(1,2),(1,3),(2,3) .
When (i,j)=(1,2), A_i+A_j=2+3=5. This is the maximum value, so the answer is 5.

Sample Input 2

3
10 71 84 33 6 47 23 25

Sample Output 2

81
94
155
155
155
155
155

Sample Input 3

4
75 26 45 72 81 47 97 97 2 2 25 82 84 17 56 32

Sample Output 3

101
120
147
156
156
178
194
194
194
194
194
194
194
194
194

Solution in Rust (1.15.1) (judge verdict: Accepted)

use std::io::*;
use std::str::FromStr;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

fn naive(n: usize, aseq: &Vec<i64>) -> Vec<i64> {
    let m = 1 << n;
    let mut ret = vec![0; m];
    for i in 1..m {
        for j in 0..i + 1 {
            for k in j + 1..i + 1 {
                if i < (j | k) {
                    continue;
                }
                ret[i] = std::cmp::max(ret[i], aseq[j] + aseq[k]);
            }
        }
    }
    ret
}

fn solve(n: usize, aseq: &Vec<i64>) -> Vec<i64> {
    let m = 1 << n;
    let mut anss = vec![0; m];
    let mut candidates = vec![vec![(0, 0), (0, 0)]; m];
    for i in 1..m {
        anss[i] = anss[i - 1];
        candidates[i] = vec![(aseq[i], i), (aseq[0], 0)];
        for j in 0..n {
            if (i & (1 << j)) == 0 {
                continue;
            }
            let t = i ^ (1 << j);
            let temp1 = candidates[t][0];
            let temp2 = candidates[t][1];
            candidates[i].push(temp1);
            candidates[i].push(temp2);
        }
        candidates[i].sort();
        candidates[i].dedup();
        candidates[i].reverse();
        anss[i] = std::cmp::max(anss[i - 1], candidates[i][0].0 + candidates[i][1].0);
        // println!("{:?}", candidates[i]);
    }
    anss
}

fn main() {
    let n = read::<usize>();
    let m = 1 << n;
    let mut aseq = vec![0; m];
    for i in 0..m {
        aseq[i] = read::<i64>();
    }
    let ret = solve(n, &aseq);
    // let ret = naive(n, &aseq);
    for i in 1..m {
        println!("{}", ret[i]);
    }
}

#[allow(dead_code)]
struct XorShift {
    x: u32,
    y: u32,
    z: u32,
    w: u32,
}
#[allow(dead_code)]
impl XorShift {
    fn new() -> XorShift {
        XorShift {
            x: 0x34fb2383,
            y: 0x327328fa,
            z: 0xabd4b54a,
            w: 0xa9dba8d1,
        }
    }
    fn seed(s: u32) -> XorShift {
        let mut rnd = XorShift::new();
        rnd.w = s;
        rnd
    }
    fn xor128(&mut self) -> u32 {
        let t = self.x ^ (self.x << 11);
        self.x = self.y;
        self.y = self.z;
        self.z = self.w;
        self.w = (self.w ^ (self.w >> 19)) ^ (t ^ (t >> 8));
        self.w
    }
    fn next_i32(&mut self, r: i32) -> i32 {
        (self.xor128() % r as u32) as i32
    }
    fn next_i32_lr(&mut self, l: i32, r: i32) -> i32 {
        self.next_i32(r - l + 1) + l
    }
    fn next_i64(&mut self, r: i64) -> i64 {
        ((((self.xor128() as u64) << 32) + self.xor128() as u64) % r as u64) as i64
    }
    fn next_i64_lr(&mut self, l: i64, r: i64) -> i64 {
        self.next_i64(r - l + 1) + l
    }
    fn next_f64(&mut self, r: f64) -> f64 {
        (self.xor128() as f64) / (0xffffffffu32 as f64) * r
    }
    fn next_f64_lr(&mut self, l: f64, r: f64) -> f64 {
        self.next_f64(r - l) + l
    }
}

#[test]
fn test() {
    let mut rnd = XorShift::new();
    let n = 5;
    let m = 1 << n;
    let mut aseq = vec![0; m];
    for _ in 0..10000 {
        println!("{}", n);
        for i in 0..m {
            aseq[i] = rnd.next_i64(100);
            print!("{} ", aseq[i]);
        }
        println!("");
        let l = solve(n, &aseq);
        let r = naive(n, &aseq);
        println!("{:?}", l);
        println!("{:?}", r);
        assert!(l == r);
    }
}