专栏文章
题解:P6820 [PA 2012 Finals] Two Cakes
P6820题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mingybbi
- 此快照首次捕获于
- 2025/12/02 02:14 3 个月前
- 此快照最后确认于
- 2025/12/02 02:14 3 个月前
蓝色的思维题能不能去死啊。
首先考虑 的暴力。定义 表示到了 的第 位, 的第 位时的最小时间。
有递推式如下:
考虑优化。由于 都是排列,所以 最多出现 次,可以记忆化搜索。又注意到 的转移实则就是平移,于是考虑将这种情况转移到前面最近的 的位置即可,可以通过二分进行实现。
二分查找位置的方法:由于平移时 是不变的,所以预处理出对于每个 ,所有 的 的位置,然后排序即可。
正解代码
CPP#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll N = 1e6 + 5;
ll n, a[N], b[N], pos[N], dp[N];
vector<ll> vec[N << 1];
ll dfs(ll i, ll j) {
if (a[i] == b[j]) {
if (dp[i] != -1) {
return dp[i];
}
return dp[i] = min(dfs(i - 1, j), dfs(i, j - 1)) + 1;
}
ll d = i - j + n;
ll p = lower_bound(vec[d].begin(), vec[d].end(), i) - vec[d].begin() - 1;
if (p == -1) {
return max(i, j);
}
p = vec[d][p];
return dfs(p, j - (i - p)) + i - p;
}
void solve() {
memset(dp, -1, sizeof dp);
scanf("%lld", &n);
for (ll i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
pos[a[i]] = i;
}
for (ll i = 1; i <= n; i++) {
scanf("%lld", &b[i]);
vec[pos[b[i]] - i + n].push_back(pos[b[i]]);
}
cout << dfs(n, n) << "\n";
}
int main() {
solve();
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...