CF1700F Puzzle 解题报告
CF1700F Puzzle 解题报告
CF1700F Puzzle - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题意
给定两个 的 矩阵 和 ,定义一次操作为交换 中任意两个相邻的位置中的值,输出使得 的最小操作次数,如果无法使 则输出 。
Sol
若和都只有一行,则答案就是(为前个位置的前缀和)。
推广到行,因为题目没有要求交换次序,所以我们可以从数组起始往后递推。
若将的挪下去,则。
可以想到,若与同号,那么这次交换是不需要的,可以放到处进行。
而若与异号,我们交换次,节省了次。
因为题目中没有说一定要上下或左右交换,所以我们以上是进行了上下交换,即把原本 若且 或 且 的两波左右交换用一波上下交换代替,推广到,就是用次上下交换代替了次左右交换。
而若以上操作不如左右交换优秀,那么在后面会再进行次上下交换以补救。恰好最终贡献还是,思想类似于 反悔自动机的差值相消思想 。
要注意这道题虽然 看起来人畜无害 ,但也是得开的,因为中间的累加约等于。
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MN = 4e5 + 5;
int n;
int a[2][MN], b[2][MN], dp[2][MN];
signed main() {
ios::sync_with_stdio(false), cin.tie(0);
cin >> n;
int sum = 0;
for (int i = 0; i <= 1; ++i)
for (int j = 1; j <= n; ++j) cin >> a[i][j], sum += a[i][j];
for (int i = 0; i <= 1; ++i)
for (int j = 1; j <= n; ++j) cin >> b[i][j], sum -= b[i][j];
if (sum != 0) {
puts("-1");
return 0;
}
int sum1 = 0, sum2 = 0;
ll ans = 0;
for (int i = 1; i <= n; ++i) {
sum1 += a[0][i] - b[0][i];
sum2 += a[1][i] - b[1][i];
if (sum1 < 0 && sum2 > 0) {
int k = min(-sum1, sum2);
ans += k;
sum1 += k, sum2 -= k;
}
else if (sum1 > 0 && sum2 < 0) {
int k = min(sum1, -sum2);
ans += k;
sum1 -= k, sum2 += k;
}
ans += abs(sum1) + abs(sum2);
}
cout << ans << '\n';
return 0;
}
本文来自博客园,作者:zjsqwq,转载请注明原文链接:https://www.cnblogs.com/zjsqwq/p/16442980.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App