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);
    }
}


Measured memory_bytes: 131324