题解:P13687 【MX-X16-T5】「DLESS-3」XOR and Rockets
Link & Cnblogs.
妙妙题。
前缀异或很丑,考虑放在
这里有个小技巧:我们先将
翻转后问题变为求单调不增的
若不修改,枚举
但这个 dp 是错误的。修改的
考虑整个东西的形态,对于一个进行操作的位置
最厉害的一步:假设我们已经构造出了一种方案使每个段都局部合法,实际上我们仅需
所以可以直接忽略这部分,仅需再用一个类似的 dp 求满足局部合法性的答案,记为
// godmoo's code
#define ckmn(a, b) (a = min(a, b))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
const int N = 5005;
const int V = 1 << 13;
int n, a[N], b[N]; ll f[2][1 << 13], g[2][1 << 13], ans;
void solve(){
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i]; reverse(a + 1, a + n + 1);
for(int i = 1; i <= n; i++) cin >> b[i]; reverse(b + 1, b + n + 1);
for(int i = n; i; i--) a[i] ^= a[i - 1];
mem(f, 0x3f), mem(g, 0x3f);
fill(f[1], f[1] + V, b[1]), f[1][a[1]] = 0;
for(int i = 2; i <= n; i++){
mem(f[i & 1], 0x3f);
for(ll j = V - 1, mn = 1e18; ~j; j--){
if((a[i] ^ j) <= j) ckmn(f[i & 1][a[i] ^ j], f[~i & 1][j]);
ckmn(f[i & 1][j], ckmn(mn, f[~i & 1][j]) + b[i]);
}
}
ans = *min_element(f[n & 1], f[n & 1] + V);
fill(g[1], g[1] + V, b[1]);
for(int i = 2; i <= n; i++){
mem(g[i & 1], 0x3f);
ll mn = *min_element(g[~i & 1], g[~i & 1] + V);
for(int j = 0; j < V; j++){
g[i & 1][j] = mn + b[i];
if((a[i] ^ j) <= j) ckmn(g[i & 1][a[i] ^ j], g[~i & 1][j]);
}
}
ckmn(ans, *min_element(g[n & 1], g[n & 1] + V));
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int Cas; for(cin >> Cas; Cas; Cas--) solve();
cout << flush;
return 0;
}