题解P2133 天作之和

· · 题解

-0x3f 闲话

蒟蒻的第一篇题解~

0x00 简要题意

这道题非常的扯淡哈,第一次看非常的蒙,这里就给一下简化题意。

给你一个字符串 A 每次操作可以交换 A 串里相邻的两个数字,看多少次操作能把他变成 S 串,输出第二小的操作次数。

0x01分析

首先,我们解决这个第二小,可以发现,在操作次数大于 2 时,第一小和第二小没有区别。否则,第二小会比第一小多两次操作。

可以发现这就是一个求逆序对的题啊。

0x02 实现

首先,我们把 A 串中每一个数字在什么位置记录在 vis 数组里。

然后。就是根据 vis 数组记录 S 串的每一个数字应该在相对于 A 数组的位置。

有点绕,我们拿样例解释一下。

$S$ : ```1 2 3 4 5 6``` $vis$ : ```1 2 3 6 5 4``` 操作后的 $S$ : ```1 2 3 6 5 4``` 然后计算操作后的 $S$ 中逆序对的数量就行了。 逆序对,就用 $O(n^2)$ 的暴力算法吧。 ## 0x03 代码 期待已久的代码环节! ``` //by syr1125 //luogu 题解 #include <bits/stdc++.h> using namespace std; string a, b; int vis[10]; int main() { cin >> a >> b; for (int i = 0; i < a.size(); i ++) { vis[a[i] - '0'] = i + 1; } for (int i = 0; i < b.size(); i ++) { b[i] = vis[b[i] - '0']; } //存储 int cnt = 0; for (int i = 0; i < b.size(); i ++) { for (int j = i + 1; j < b.size(); j ++) { if (b[j] < b[i]) cnt ++; } } //计算逆序对 //快乐的输出 if (cnt <= 2) cout << cnt + 2 << endl; else cout << cnt << endl; return 0; //好习惯 } ``` ###### ~~管理员大大通过吧。~~