#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
int a[MAXN+1], ans[MAXN+2];
vector<int> ins[MAXN+2], del[MAXN+2]; // we'll do a “sweep‑line” over i
void add_range(int L, int R, int val){
if(L>R) return;
ins[L].push_back(val);
del[R+1].push_back(val);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while(T--){
int n,k;
cin >> n >> k;
for(int i=1;i<=n;i++){
cin >> a[i];
ans[i] = a[i]; // singleton [i..i] gives nor=a[i]
ins[i].clear();
del[i].clear();
}
ins[n+1].clear(); del[n+1].clear();
// lst1[j] = last position ≤ r where bit j was 1
static int lst1[17];
fill(lst1, lst1+k, 0);
// For each right endpoint r = 1..n:
for(int r=1;r<=n;r++){
// Update last-one positions
for(int j=0;j<k;j++){
if(a[r] & (1<<j)) lst1[j] = r;
}
// Build the O(k) segments by walking backward through
// the “breakpoints” lst1[j] and lst1[j]-1, as in the editorial.
// Here we maintain a map from cutoff ℓ0 to a pair (v_even,v_odd),
// then scan it in order to generate explicit segments [lb,ub].
map<int, pair<int,int>> mp;
// Start with the full segment [0..r], whose values depend
// on parity of r itself; you can check the editorial for
// exactly how they seed it.
// ...
// (cf. LegendStane’s code around L33–L35)
// Now mp is a sorted map whose keys −ℓ0 (breakpoints)
// carry partial contributions. We do exactly what L35–L37 do:
pair<int,int> ad = { (1<<k)-1, 0 };
if(r%2==1) swap(ad.first, ad.second);
int ub = r;
for(auto &it : mp){
int lb = -it.first + 1; // segment from lb..ub
auto delta = it.second; // how bits flip on crossing that breakpoint
// schedule range‑updates for parity
// even‑ℓ get ad.first, odd‑ℓ get ad.second
int lb_even = (lb%2==0 ? lb : lb+1);
int lb_odd = (lb%2==1 ? lb : lb+1);
if(lb_even <= ub) add_range(lb_even, ub, ad.first);
if(lb_odd <= ub) add_range(lb_odd, ub, ad.second);
// incorporate the delta into ad and shrink ub
ad.first += delta.first;
ad.second += delta.second;
ub = -it.first;
}
// final segment from ℓ=1..ub
{
int lb=1;
int lb_even = (lb%2==0 ? lb : lb+1);
int lb_odd = (lb%2==1 ? lb : lb+1);
if(lb_even <= ub) add_range(lb_even, ub, ad.first);
if(lb_odd <= ub) add_range(lb_odd, ub, ad.second);
}
}
// Now do the sweep‑line over i = 1..n, maintaining a multiset of active values
multiset<int> cur;
for(int i=1;i<=n;i++){
for(int v: ins[i]) cur.insert(v);
for(int v: del[i]) cur.erase(cur.find(v));
if(!cur.empty())
ans[i] = max(ans[i], *cur.rbegin());
}
// Output
for(int i=1;i<=n;i++){
cout << ans[i] << " \n"[i==n];
}
}
return 0;
}