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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;

struct P
{
    public int A, B;

    public P(int a, int b)
    {
        A = a;
        B = b;
    }
}

struct S
{
    public int N, Index;

    public S(int n, int i)
    {
        N = n;
        Index = i;
    }
}

#region PriorityQueue

/// <summary>
/// 指定した型のインスタンスを最も価値が低い順に取り出すことが可能な可変サイズのコレクションを表します．
/// </summary>
/// <typeparam name="T">優先度付きキュー内の要素の型を指定します．</typeparam>
/// <remarks>内部的にはバイナリヒープによって実装されています．</remarks>
public class PriorityQueue<T>
{
    readonly List<T> heap = new List<T>();
    readonly Comparison<T> cmp;

    /// <summary>
    /// デフォルトの比較子を使用してインスタンスを初期化します．
    /// </summary>
    /// <remarks>この操作は O(1) で実行されます．</remarks>
    public PriorityQueue()
    {
        cmp = Comparer<T>.Default.Compare;
    }

    /// <summary>
    /// デリゲートで表されるような比較関数を使用してインスタンスを初期化します．
    /// </summary>
    /// <param name="comparison"></param>
    /// <remarks>この操作は O(1) で実行されます．</remarks>
    public PriorityQueue(Comparison<T> comparison)
    {
        cmp = comparison;
    }

    /// <summary>
    /// 指定された比較子を使用してインスタンスを初期化します．
    /// </summary>
    /// <param name="comparer"></param>
    /// <remarks>この操作は O(1) で実行されます．</remarks>
    public PriorityQueue(IComparer<T> comparer)
    {
        cmp = comparer.Compare;
    }

    /// <summary>
    /// 優先度付きキューに要素を追加します．
    /// </summary>
    /// <param name="item">優先度付きキューに追加される要素</param>
    /// <remarks>最悪計算量 O(log N) で実行されます．</remarks>
    public void Enqueue(T item)
    {
        var pos = heap.Count;
        heap.Add(item);
        while (pos > 0)
        {
            var par = (pos - 1) / 2;
            if (cmp(heap[par], item) <= 0)
                break;
            heap[pos] = heap[par];
            pos = par;
        }

        heap[pos] = item;
    }

    /// <summary>
    /// 優先度付きキューから最も価値が低い要素を削除し，返します．
    /// </summary>
    /// <returns>優先度付きキューから削除された要素．</returns>
    /// <remarks>最悪計算量 O(log N) で実行されます．</remarks>
    public T Dequeue()
    {
        var ret = heap[0];
        var pos = 0;
        var x = heap[heap.Count - 1];

        while (pos * 2 + 1 < heap.Count - 1)
        {
            var lch = pos * 2 + 1;
            var rch = pos * 2 + 2;
            if (rch < heap.Count - 1 && cmp(heap[rch], heap[lch]) < 0) lch = rch;
            if (cmp(heap[lch], x) >= 0)
                break;
            heap[pos] = heap[lch];
            pos = lch;
        }

        heap[pos] = x;
        heap.RemoveAt(heap.Count - 1);
        return ret;
    }

    /// <summary>
    ///  優先度付きキューに含まれる最も価値が低い要素を削除せずに返します．
    /// </summary>
    /// <returns>優先度付きキューに含まれる最も価値が低い要素．</returns>
    /// <remarks>この操作は O(1) で実行されます．</remarks>
    public T Peek()
    {
        return heap[0];
    }

    /// <summary>
    /// 優先度付きキュー内の要素の数を取得します．
    /// </summary>
    /// <returns>優先度付キュー内にある要素の数</returns>
    /// <remarks>最悪計算量 O(1) で実行されます．</remarks>
    public int Count
    {
        get { return heap.Count; }
    }

    /// <summary>
    /// 優先度付きキュー内に要素が存在するかどうかを O(1) で判定します．
    /// </summary>
    /// <returns>優先度付キュー内にある要素が存在するならば true，そうでなければ　false．</returns>
    /// <remarks>この操作は O(1) で実行されます．</remarks>
    public bool Any()
    {
        return heap.Count > 0;
    }

    /// <summary>
    /// 優先度付きキューに含まれる要素を昇順に並べて返します．
    /// </summary>
    /// <remarks>この操作は計算量 O(N log N)で実行されます．</remarks>
    public T[] Items
    {
        get
        {
            var ret = heap.ToArray();
            Array.Sort(ret, cmp);
            return ret;
        }
    }
}

#endregion

public class Program
{
    private int N;
    private int[] A;
    private int L;

    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        A = sc.IntArray();
        L = 1 << N;
        var array = new S[L];
        for (int i = 0; i < L; i++)
        {
            array[i] = new S(A[i], i);
        }

        Array.Sort(array, (a, b) => -a.N.CompareTo(b.N));

        var pq = new PriorityQueue<P>((a, b) => -(array[a.A].N + array[a.B].N).CompareTo(array[b.A].N + array[b.B].N));

        for (int i = 0; i < L - 1; i++)
        {
            pq.Enqueue(new P(i, i + 1));
        }

        int max = L - 1;

        int[] ans = new int[L - 1];

        while (max >= 1)
        {
            var p = pq.Dequeue();
            int or = array[p.A].Index | array[p.B].Index;
            int sum = array[p.A].N + array[p.B].N;
            if (or <= max)
            {
                for (int i = or; i <= max; i++)
                {
                    ans[i - 1] = sum;
                }

                max = or - 1;
            }

            //Console.WriteLine($"{array[p.A].Index} {array[p.B].Index}");
            if (array[p.A].Index <= max && p.B + 1 < L)
            {
                p.B++;
                pq.Enqueue(p);
            }
        }

        Console.WriteLine(string.Join("\n", ans));
    }

    public static void Main(string[] args)
    {
        new Program().Solve();
    }
}

class Scanner
{
    public Scanner()
    {
        _pos = 0;
        _line = new string[0];
    }

    const char Separator = ' ';
    private int _pos;
    private string[] _line;

    #region スペース区切りで取得

    public string Next()
    {
        if (_pos >= _line.Length)
        {
            _line = Console.ReadLine().Split(Separator);
            _pos = 0;
        }

        return _line[_pos++];
    }

    public int NextInt()
    {
        return int.Parse(Next());
    }

    public long NextLong()
    {
        return long.Parse(Next());
    }

    public double NextDouble()
    {
        return double.Parse(Next());
    }

    #endregion

    #region 型変換

    private int[] ToIntArray(string[] array)
    {
        var result = new int[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = int.Parse(array[i]);
        }

        return result;
    }

    private long[] ToLongArray(string[] array)
    {
        var result = new long[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = long.Parse(array[i]);
        }

        return result;
    }

    private double[] ToDoubleArray(string[] array)
    {
        var result = new double[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = double.Parse(array[i]);
        }

        return result;
    }

    #endregion

    #region 配列取得

    public string[] Array()
    {
        if (_pos >= _line.Length)
            _line = Console.ReadLine().Split(Separator);

        _pos = _line.Length;
        return _line;
    }

    public int[] IntArray()
    {
        return ToIntArray(Array());
    }

    public long[] LongArray()
    {
        return ToLongArray(Array());
    }

    public double[] DoubleArray()
    {
        return ToDoubleArray(Array());
    }

    #endregion
}