// Original C++ solution (slower):
#include <cstdio>

#include <cstring>

#include <algorithm>



int Max[550000], cMax[550000]; 

int n, a[550000], Ans[550000];

int o[4];



int main()

{

	scanf("%d", &n);

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

	memset(Max, -1, sizeof(Max));

	memset(cMax, -1, sizeof(cMax));

	Max[0] = a[0];

	if(a[1] > a[0]) Max[1] = a[1], cMax[1] = a[0];

	else Max[1] = a[0], cMax[1] = a[1];

	Ans[1] = a[0] + a[1];

	printf("%d\n", a[0] + a[1]);

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

	{

		int S = 0, b;

		for(int j = 17; j >= 0; j--)

		{

			if((i >> j) & 1)

			{

				S = i ^ (1 << j);

				b = j;

				break;

			}

		}

		b = 1 << b;

		for(int j = S; ; j = ((j - 1) & S))

		{

			int u = a[b ^ j];

			if(u > Max[i]) cMax[i] = Max[i], Max[i] = u;

			else if(u > cMax[i]) cMax[i] = u;

			if(j == 0) break;

		}

		o[0] = Max[i]; o[1] = cMax[i]; o[2] = Max[S]; o[3] = cMax[S];

		std::sort(o, o + 4);

		Max[i] = o[3]; cMax[i] = o[2];

		if(cMax[i] == -1)

		{

			Ans[i] = Ans[i - 1];

			printf("%d\n", Ans[i]);

		}

		else

		{

			Ans[i] = std::max(Max[i] + cMax[i], Ans[i - 1]);

			printf("%d\n", Ans[i]);

		}

	}

	return 0;

}

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

#include<cstdio>

#include<cstring>

#include<cstdlib>

#include<algorithm>

#include<cmath>

using namespace std;

int n,ans=0,tot;

int num[300010];

struct node{

	int maxx,cmax;

}a[300010];

void chan(int x,int pos){

	if(x==a[pos].cmax || x==a[pos].maxx)  return ;

	if(num[x]>num[a[pos].maxx]){

		a[pos].cmax=a[pos].maxx;a[pos].maxx=x;

	}

	else{

		if(num[x]>num[a[pos].cmax])  a[pos].cmax=x;

	}

}

int main(){

	scanf("%d",&n);

	int i,j;

	tot=(1<<n);num[tot]=0;

	for(i=0;i<tot;++i){

		scanf("%d",&num[i]);a[i].maxx=i;a[i].cmax=tot;

	}

	for(i=1;i<tot;++i){

		for(j=0;j<n;++j){

			if(i&(1<<j)){

				int tt=i^(1<<j);

				chan(a[tt].maxx,i);

				chan(a[tt].cmax,i);

			}

		}

	}

	ans=0;

	for(i=1;i<tot;++i){

		ans=max(ans,num[a[i].maxx]+num[a[i].cmax]);

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

	}	

	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;

	}