// Original C++ solution (slower):
//Zory-2018

#include<cmath>

#include<cstdio>

#include<cstring>

#include<cstdlib>

#include<map>

#include<set>

#include<queue>

#include<deque>

#include<bitset>

#include<vector>

#include<algorithm>

#include<iostream>

#include<stack>

using namespace std;



namespace mine

{

	const int MAX_N=310000;

	typedef long long ll;

	int mymax(int x,int y) {return x>y?x:y;}



	int a[MAX_N],mx[MAX_N];

	int ans[MAX_N];

	void main()

	{

		int n;scanf("%d",&n);

		int m=1<<n;

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



		for(int k=1;k<m;k++)

		{

			ans[k]=mymax(a[0],ans[k-1]);

			mx[k]=a[0];

			for(int u=k;u>0;u=(u-1)&k)

				ans[k]=mymax(ans[k],a[u]+mx[k]),mx[k]=mymax(mx[k],a[u]);

			printf("%d\n",ans[k]);

		}

	}

};



int main()

{

	mine::main();

}


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

#include<cstring>

#include<cstdlib>

#include<algorithm>

#include<cmath>

#include<queue>

#include<vector>

#include<ctime>

#include<map>

#include<bitset>

#include<set>

#define LL long long

#define mp(x,y) make_pair(x,y)

#define pll pair<long long,long long>

#define pii pair<int,int>

using namespace std;

inline int read()

{

	int f=1,x=0;char ch=getchar();

	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}

	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}

	return x*f;

}

int stack[20];

inline void write(LL x)

{

	if(x<0){putchar('-');x=-x;}

    if(!x){putchar('0');return;}

    int top=0;

    while(x)stack[++top]=x%10,x/=10;

    while(top)putchar(stack[top--]+'0');

}

inline void pr1(int x){write(x);putchar(' ');}

inline void pr2(LL x){write(x);putchar('\n');}



const int MAX_N=20;

int bin[MAX_N];

#define pr pair<int,int>

#define FR first

#define SE second

#define MP make_pair

int a[1<<MAX_N];pr b[1<<MAX_N];

int gmax(int x,int y){return a[x]>a[y]?x:y;}

pr merge(pr x,pr y)

{

	if(a[x.FR]>a[y.FR]) return MP(x.FR,gmax(x.SE,y.FR));

	else return MP(y.FR,gmax(x.FR,y.SE));

}

void fwt(int n)

{

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

		for(int j=bin[n]-1;j>=0;j--) if(j&bin[i])

				b[j]=merge(b[j],b[j^bin[i]]);

}

int main()

{

	bin[0]=1;for(int i=1;i<MAX_N;i++) bin[i]=bin[i-1]<<1;

	

	int n;scanf("%d",&n);a[bin[n]]=0;

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

	fwt(n);

	int lst=0;

	for(int i=1;i<bin[n];i++)

	{

		lst=max(a[b[i].FR]+a[b[i].SE],lst);

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

	}

}

/*

4

75 26 45 72 81 47 97 97 2 2 25 82 84 17 56 32

*/


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

	}