// Original C++ solution (slower):
// Math = ♥️



#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>

#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;

using namespace std;



/*-------------------------------------------------------------------------------------------------------------------------*/

#define ll long long                  // Short form for long long

#define ld long double                // Short form for long double

typedef pair<ll, ll> ii;              // Pair of long long

typedef vector<ll> vi;                // Vector of long long

typedef vector<vi> vvi;               // Vector of vector of long long

typedef vector<ii> vii;               // Vector of pairs

typedef vector<vii> vvii;             // Vector of vector of pairs

#define pq priority_queue             // Max heap (To convert to min heap, use negative sign before every value)

#define ff first                      // For pairs

#define ss second                     // For pairs

#define pb push_back                  // Pushback to vector

#define mp make_pair                  // Makes pairs to be stored as pair

#define all(c) (c).begin(), (c).end() // Mainly used by me in sorting

// ordered_set adds two new functions to set - (set).find_by_order([kth element based on zero indexing]) and order_of_key()

// order_of_key returns number of elements less that parameter. If element exists, that order is its index

#define ordered_set tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update>

/*-------------------------------------------------------------------------------------------------------------------------*/



vi arr;

vii dp;

ll n;



ii solve(ll bit)

{

    if (dp[bit] == mp(-1ll, -1ll))

    {

        ii maxi = {bit, 0};

        if (arr[0] > arr[bit])

            swap(maxi.ff, maxi.ss);

        for (int i = n; i >= 0; i--)

        {

            ll check = (1 << i);

            if (bit & check)

            {

                auto c = solve(bit & (~(check)));

                if (c.ff != maxi.ff && c.ff != maxi.ss)

                {

                    if (arr[c.ff] > arr[maxi.ff])

                        maxi.ss = maxi.ff, maxi.ff = c.ff;

                    else if (arr[c.ff] > arr[maxi.ss])

                        maxi.ss = c.ff;

                }



                if (c.ss != maxi.ff && c.ss != maxi.ss)

                {

                    if (arr[c.ss] > arr[maxi.ff])

                        maxi.ss = maxi.ff, maxi.ff = c.ss;

                    else if (arr[c.ss] > arr[maxi.ss])

                        maxi.ss = c.ss;

                }

            }

        }

        dp[bit] = maxi;

    }

    return dp[bit];

}



int main(void)

{

    ios_base::sync_with_stdio(false);

    cin.tie(NULL);



    cin >> n;



    ll N = (1 << n);

    arr.resize(N);



    for (int i = 0; i < N; i++)

        cin >> arr[i];



    dp.resize(N, {-1, -1});

    dp[0] = {0, 0};

    solve(N - 1);



    ll prev = 0;

    for (int i = 1; i < N; i++)

    {

        prev = max(prev, arr[dp[i].ff] + arr[dp[i].ss]);

        cout << prev << "\n";

    }

}


// Optimized solution to the same problem (faster):
#include<cstdio>

#include<algorithm>

#define rep(i,l,r) for (int i=(l); i<=(r); i++)

using namespace std;



const int N=300010;

int n,m,a[N],r[N],mx[N];



int main(){

    scanf("%d",&m); int n=1<<m;

    for (int i=0; i<n; i++) scanf("%d",&a[i]);

    for (int i=0; i<n; i++)

        for (int j=i; j<n; j=(j+1)|i)

            r[j]=max(r[j],a[i]+mx[j]),mx[j]=max(mx[j],a[i]);

    for (int i=1; i<n; i++) printf("%d\n",r[i]=max(r[i],r[i-1]));

    return 0;

}

// Fastest known solution for this problem:
	#include <bits/stdc++.h>

	#define mx 300005

	using namespace std;



	int a[mx], n;

	vector<vector<bool> > vis(mx, vector<bool> (20, false));

	vector<vector<pair<int,int> > > memo(mx, vector<pair<int, int> > (20, {0, 0}));



	void dp(int num, int pos) {

		if(pos == 0) {

			memo[num][0].first = a[num];

			vis[num][0] = true;

			return;

		}

		if(vis[num][pos]) return;

 		vector<int> cons;

		dp(num, pos-1);

		cons.push_back(memo[num][pos-1].first);

		cons.push_back(memo[num][pos-1].second);

		if(num & (1<<(pos-1))) {

			dp(num ^ (1<<(pos-1)), pos-1);

			cons.push_back(memo[num ^ (1<<(pos-1))][pos-1].first);

			cons.push_back(memo[num ^ (1<<(pos-1))][pos-1].second);

		}

		sort(cons.begin(), cons.end(), greater<int>());

		memo[num][pos].first = cons[0];

		memo[num][pos].second = cons[1];

		vis[num][pos] = true;

	}



	int main() {

		ios_base::sync_with_stdio(false);

	    cin.tie(NULL);

	    cout.tie(NULL);



		cin >> n;

		for(int i = 0; i < (1<<n); ++i) {

			cin >> a[i];

			

		}

		for(int i = (1<<n) - 1; i >= 0; --i) {

			if(!vis[i][n]) {

				dp(i, n);

			}

		}

		int mxv = 0;

		for(int i = 1; i < 1<<n; ++i) {

			mxv = max(memo[i][n].first + memo[i][n].second, mxv);

			cout << mxv << "\n";	

		}

		return 0;

	}