大样例没问题,云斗只有20pts
#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define ll1 long long
#define int long long
const int N=3e5;
ll1 k;
int m,n,n1;
int a[N];
ll1 w[N];
void init(){
scanf("%lld%lld",&m,&k);
n=(1<<(m+1))-1;
n1=(1<<(m))-1;
for(int i=1;i<=n1;i++)
scanf("%lld",&w[i]);
for(int i=n1+1;i<=n;i++)
scanf("%lld",&a[i]);
}
struct node{
int dataa;
ll1 cost;
bool lr,isc;
ll1 lc,rc;//分给左边,右边的权值和。优先访问边有优先级
};
vector<node>my[N];
node tmp1[N],tmp2[N],tmp;
node mm[N];
int sum1,sum2;
#define ls root<<1
#define rs (root<<1)+1
void dfs(int root){//树上dp,处理出vector[i][j]。
if((ls)>n){
my[root].push_back((node){a[root],0,0,0});
return;
}
dfs(ls);dfs(rs);
int x,y;
sum1=sum2=0;
x=my[ls].size();
y=my[rs].size();
mm[y-1]=my[rs][y-1];
for(int i=y-2;i>=0;i--){
mm[i]=my[rs][i];
if(mm[i+1].cost<=mm[i].cost)mm[i]=mm[i+1];
}
for(int i=0;i<x;i++){
tmp=my[ls][i];
tmp.isc=0;
tmp.lr=0;
if(mm[y-1].dataa>tmp.dataa){
int l=0,r=y-1,mid;
while(l<r){
mid=(l+r)/2;
if(my[rs][mid].dataa>tmp.dataa)r=mid;
else l=mid+1;
}
tmp.cost+=mm[l].cost;
tmp.lc=tmp.cost-mm[l].cost;//
tmp.rc=mm[l].cost;//
if(w[root]<mm[l].cost){
tmp.cost=tmp.cost-mm[l].cost+w[root],tmp.isc=1;
tmp.rc=0;//
}
}else tmp.cost=tmp.cost+w[root],tmp.isc=1;
if(tmp.cost<=k)tmp1[++sum1]=tmp;
}
mm[x-1]=my[ls][x-1];
for(int i=x-2;i>=0;i--){
mm[i]=my[ls][i];
if(mm[i+1].cost<=mm[i].cost)mm[i]=mm[i+1];
}
for(int i=0;i<y;i++){
tmp=my[rs][i];
tmp.isc=0;
tmp.lr=1;
if(mm[x-1].dataa>tmp.dataa){
int l=0,r=x-1,mid;
while(l<r){
mid=(l+r)/2;
if(my[ls][mid].dataa>tmp.dataa)r=mid;
else l=mid+1;
}
if(tmp.cost+mm[l].cost<=k){
tmp.cost=tmp.cost+mm[l].cost;
tmp.rc=tmp.cost-mm[l].cost;//
tmp.lc=mm[l].cost;//
tmp2[++sum2]=tmp;
}
}
}
tmp1[sum1+1]=tmp2[sum2+1]=(node){1145141919,1145141919,0,0};
for(int i=1,j=1;i<=sum1||j<=sum2;){//归并保持单调性
if(tmp1[i].dataa<tmp2[j].dataa)
my[root].push_back(tmp1[i]),i++;
else my[root].push_back(tmp2[j]),j++;
}
}
ll1 dfs1(int root,int now,ll1 K){//走
if(ls>n){
printf("%lld ",a[root]);
return K;//剩余的权
}
bool LorR=0;int lenth=my[root].size();
bool iscc=0;
int Lc,Rc;
for(int i=0;i<lenth;i++){
if(my[root][i].dataa==now){
LorR=my[root][i].lr;
Lc=my[root][i].lc,Rc=my[root][i].rc;
if(my[root][i].isc==1)
iscc=1;
}
}
if(iscc==1)K-=w[root];//被使用的
ll1 tK=K;
K=(LorR==0?Rc:Lc);
ll1 K1;
K1=tK-K;
int too=0;
K=K+dfs1((ls)+LorR,now,K1);//继续目标,卓玛赵常升起
int x=my[ls].size();
int y=my[rs].size();
if(LorR==1){//查找左边数
for(int i=0;i<x;i++){
if(my[ls][i].dataa<now)continue;
if(my[ls][i].cost<=K)too=my[ls][i].dataa;
}
return dfs1(ls,too,K);
}else{//查找右边/替换
if(iscc==1){
for(int i=0;i<y;i++){
if(my[rs][i].cost<=K)too=my[rs][i].dataa;
}
if(too>now)K+=w[root];
return dfs1(rs,too,K);
}else{
for(int i=0;i<y;i++){
if(my[rs][i].dataa<now)continue;
if(my[rs][i].cost<=K)too=my[rs][i].dataa;
}
return dfs1(rs,too,K);
}
}
}
void work(){
for(int i=0;i<=n;i++)my[i].clear();
dfs(1);
int x=my[1][my[1].size()-1].dataa;
dfs1(1,x,k);
}
signed main(){
// freopen("maze.in","r",stdin);
// freopen("maze.out","w",stdout);
int T;
scanf("%lld",&T);
while(T--){
init();
work();
printf("\n");
}
return 0;
}