30pts 求助 悬关
查看原帖
30pts 求助 悬关
637796
Xy_top楼主2024/11/26 21:33
#include <bits/stdc++.h>
#define int long long
#define For(i, a, b) for (int i = (a); i <= (b); i ++)
#define foR(i, a, b) for (int i = (a); i >= (b); i --)
using namespace std;
int n, K, S;
int a[18][1 << 19], f[18][1 << 19];
int q[1 << 19], t_[1 << 19], w[1 << 19];
int x[1 << 19], y[1 << 19], bel[1 << 19], rk[2][1 << 19];
vector <int> ans;
const int inf = 1000000000000000000LL;
void merge_sort (int u, int k, int l, int r) {
	x[u] = l;
	y[u] = r;
	if (l == r) {
		a[k][l] = q[l + S - 1];
		return;
	}
	int mid = l + r >> 1;
	merge_sort (u << 1, k + 1, l, mid);
	merge_sort (u << 1 | 1, k + 1, mid + 1, r);
	int x = l, y = mid + 1, cnt = l - 1;
	while (x != mid + 1 && y != r + 1) {
		if (a[k + 1][x] < a[k + 1][y]) t_[++ cnt] = a[k + 1][x ++];
		else t_[++ cnt] = a[k + 1][y ++];
	}
	if (x == mid + 1) {
		while (y != r + 1) t_[++ cnt] = a[k + 1][y ++];
	} else while (x != mid + 1) t_[++ cnt] = a[k + 1][x ++];
	For (i, l, r) a[k][i] = t_[i];
}
void func (int u, int k) {
	int l = x[u], r = y[u];
	int mid = l + r >> 1;
	For (i, l, mid) {
		bel[a[k + 1][i] ] = 0;
		rk[0][a[k + 1][i] ] = i;
	}
	For (i, mid + 1, r) {
		bel[a[k + 1][i] ] = 1;
		rk[1][a[k + 1][i] ] = i;
	}
}
void dp (int u, int k) {
 	int l = x[u], r = y[u];
	if (u >= S) return void (f[k][l] = 0);
	int mid = l + r >> 1;
	dp (u << 1, k + 1);
	dp (u << 1 | 1, k + 1);
	func (u, k);
	int tl = l, tr = mid + 1;
	For (i, l, r) {
		if (!bel[a[k][i] ]) {//在左子树
			while (tr <= r && a[k + 1][tr] < a[k][i]) ++ tr;
			while (tr <= r && f[k + 1][tr] >= inf) ++ tr;
			f[k][i] = f[k + 1][rk[0][a[k][i] ] ] + min (w[u], (tr == r + 1) ? inf : f[k + 1][tr]);
		} else {//在右子树
			while (tl <= mid && a[k + 1][tl] < a[k][i]) ++ tl;
			while (tl <= mid && f[k + 1][tl] >= inf) ++ tl;
			if (tl == mid + 1) f[k][i] = inf;
			else f[k][i] = f[k + 1][tl] + f[k + 1][rk[1][a[k][i] ] ];
		}
	}
}
int dfs (int u, int k, int z) {
	int l = x[u], r = y[u];
	int mid = l + r >> 1;
	if (u >= S / 2) {//u 是倒数第二层
		if (q[u << 1] < q[u << 1 | 1] || q[u << 1] > q[u << 1 | 1] && w[u] <= z) {
			ans.push_back (q[u << 1]);
			ans.push_back (q[u << 1 | 1]);
			if (q[u << 1] < q[u << 1 | 1]) return 0;
			return w[u];
		} else {
			ans.push_back (q[u << 1 | 1]);
			ans.push_back (q[u << 1]);
			return 0;
		}
	}
	func (u, k);
	int node = 0, tmp = 0;
	For (i, l, r) if (f[k][i] <= z) node = i;
	if (!bel[a[k][node] ]) {//接下来要走的节点在左子树,要么强制,要么右边大于左边
		For (i, mid + 1, r) if (a[k + 1][i] > a[k][node] && f[k + 1][i] < inf) {
			tmp = i;
			break;
		}
		if (tmp == 0) {
			int c = dfs (u << 1, k + 1, z - w[u]);
			return c + w[u] + dfs (u << 1 | 1, k + 1, z - w[u] - c);
		}
		int zzz = dfs (u << 1, k + 1, z - min (w[u], f[k + 1][tmp]) );
		int c = z - min (w[u], f[k + 1][tmp]) - zzz;//走右子树剩下的
		if (min (w[u], f[k + 1][tmp]) == w[u]) {
			bool ff = 0;
			For (i, mid + 1, r) if (f[k][i] <= z - zzz && a[k + 1][i] > a[k][node]) ff = 1;
			if (ff) return zzz + dfs (u << 1 | 1, k + 1, w[u] + c);
			else return w[u] + zzz + dfs (u << 1 | 1, k + 1, c);
		} else return zzz + dfs (u << 1 | 1, k + 1, z - zzz);
	} else {//接下来要走的节点在右子树
		int tmp = 0;
		For (i, l, mid) if (a[k + 1][i] > a[k][node] && f[k + 1][i] < inf) {
			tmp = i;
			break;
		}
		int x = dfs (u << 1 | 1, k + 1, z - f[k + 1][tmp]);
		return x + dfs (u << 1, k + 1, z - x);
	}
}
void solve () {
	ans.clear ();
	cin >> n >> K;
	S = 1 << n;
	For (i, 1, S - 1) cin >> w[i];
	For (i, S, 2 * S - 1) cin >> q[i];
	merge_sort (1, 1, 1, S);
	dp (1, 1);
	dfs (1, 1, K);
	for (int i : ans) cout << i << ' ';
}
signed main () {
	int _ = 1;
	cin >> _;
	while (_ --) {
		solve ();
		cout << '\n';
	}
	return 0;
}
2024/11/26 21:33
加载中...