// Original C++ solution (slower):
#include <stdio.h>

#include <string.h>

#include <algorithm>

#define MN (1<<18)

int n,a[MN+5],b[MN+5][2],c[MN+5][2],ans=0;

int cnt=0;

void xxx(int to,int frm,int p){

	if(c[to][0]==c[frm][p]||c[to][1]==c[frm][p]) return;

	if(b[to][0]<b[frm][p]){

		b[to][1]=b[to][0];  c[to][1]=c[to][0];

		b[to][0]=b[frm][p]; c[to][0]=c[frm][p];

	}else if(b[to][1]<b[frm][p]){

		b[to][1]=b[frm][p]; c[to][1]=c[frm][p];

	}

}

void work(int x){

	for(int j=1;j<(1<<18);j<<=1)

		if(x&j){

			xxx(x,x^j,0);

			xxx(x,x^j,1);

		}

}

int main(){

	scanf("%d",&n);

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

		scanf("%d",&a[i]);

	memset(c,0xff,sizeof(c));

	b[0][0]=a[0]; c[0][0]=0;

	b[0][1]=-1;   c[0][1]=-1;

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

		b[i][0]=a[i]; c[i][0]=i;

		work(i);

		ans=std::max(ans,b[i][0]+b[i][1]);

		printf("%d\n",ans);

	}

}

// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

#define taskname "OrPlusMax"

#define int long long

using namespace std;



vector<int> a;

void update(int i, pair<int, int> &p)

{

    if (i == p.first || i == -1) return;

    if (p.first == -1 || a[i] > a[p.first])

    {

        swap(p.first, p.second);

        p.first = i;

    }

    else if (p.second == -1 || a[i] > a[p.second]) p.second = i;

}



main()

{

    ios_base::sync_with_stdio(false);

    cin.tie(nullptr);   cout.tie(nullptr);

    if (ifstream("test.inp"))

    {

        freopen("test.inp", "r", stdin);

        #ifdef CHECKING

            freopen(taskname".out", "w", stdout);

        #else

            freopen("test.out", "w", stdout);

        #endif //CHECKING

    }

    else if (ifstream(taskname".inp"))

    {

        freopen(taskname".inp", "r", stdin);

        freopen(taskname".out", "w", stdout);

    }



    int n;  cin >> n;

    a.resize(1 << n);

    for (int &i : a) cin >> i;

    vector<pair<int, int>> v(1 << n, {-1, -1});

    vector<int> ans(1 << n, 0);

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

    {

        update(i, v[i]);

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

            if (((i >> (j - 1)) & 1) == 0)

            {

                int x = i ^ (1 << (j - 1));

                update(v[i].first, v[x]);

                update(v[i].second, v[x]);

            }

        if (i)

        {

            ans[i] = max(ans[i - 1], a[v[i].first] + a[v[i].second]);

            cout << ans[i] << '\n';

        }

    }

}


// 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;

	}