题目传送门:https://www.luogu.com.cn/problem/P3531

题意

给出只包含大写字母的字符串 A 和字符串 B,每次可以交换字符串 A 两个相邻的字符,求 A 变成 B 的最小交换次数。

思路

这道题给了我一丝熟悉感,就像给定一个数组,我们每次可以交换数组中相邻的两个元素,求将它变成有序需要的最小的交互次数,也就是求其逆序对个数。其实它们的运作方式是完全,只不过这里只是将“有序”的基准变成了 “变成 B”。

如果字符串中的字符无法让我们直接完成求解操作,我们需要先利用下标进行一个转换操作。以下面这组用例为例:

4
CABC
CCAB

我们先对 A 编号,并按字符提取下标:

1 2 3 4
C A B C
=>
A: 2
B: 3
C: 1 4

接着,我们根据提取的下标对字符串 B 进行编号:

C C A B
=>
1 4 2 3

最后,我们可以通过对数列 1 4 2 3 求逆序对得到答案啦~

参考代码

求逆序对常用的方法有两种,一种是归并排序,在合并的时候用 ans += mid - i + 1 进行求解;另一种是树状数组,遍历数组时用ans += i - sum(a[i]) 求解。

1. 归并排序

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1e6 + 10;
long long ans, n;
// lt[i]表示字母(i+'A')访问到st[i]的下标
// a[] 表示处理之后元素值各不相同的数组,temp[] 是归并过程中用到的中间数组
int lt[26], a[maxn], temp[maxn];
vector<int> st[26]; // st[i][j] 表示第j个字母(i+'A')所在的下标
string strA, strB;void mergeSort(int left, int right) {if (left == right) {return ;}int mid = left + (right - left) / 2;int i = left, j = mid + 1, k = left;mergeSort(left, mid);mergeSort(mid + 1, right);while (i <= mid && j <= right) {if (a[i] <= a[j]) {temp[k++] = a[i++];} else {temp[k++] = a[j++];ans += mid - i + 1; // 求逆序对}}while (i <= mid) {temp[k++] = a[i++];}while (j <= right) {temp[k++] = a[j++];}for (int l = left; l <= right; l++) {a[l] = temp[l];}
}int main()
{cin >> n;cin >> strA >> strB;for (int i = 0; i < n; i++) {int idx = strA[i] - 'A';st[idx].push_back(i + 1);}for (int i = 0; i < n; i++) {int idx = strB[i] - 'A';a[i + 1] = st[idx][lt[idx]++];}mergeSort(1, n);cout << ans << endl;return 0;
}

2. 树状数组

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1e6 + 10;
long long ans, n;
// lt[i]表示字母(i+'A')访问到st[i]的下标
// a[] 表示处理之后元素值各不相同的数组,temp[] 是归并过程中用到的中间数组
int lt[26], a[maxn], c[maxn];
vector<int> st[26]; // st[i][j] 表示第j个字母(i+'A')所在的下标
string strA, strB;int lowbit(int x) {return x & (-x);
}void update(int i, int x) {for ( ; i <= n; i += lowbit(i))c[i] += x;
}int sum(int i) {int res = 0;for ( ; i >= 1; i -= lowbit(i))res += c[i];return res;
}int main()
{cin >> n;cin >> strA >> strB;for (int i = 0; i < n; i++) {int idx = strA[i] - 'A';st[idx].push_back(i + 1);}for (int i = 0; i < n; i++) {int idx = strB[i] - 'A';a[i + 1] = st[idx][lt[idx]++];}for (int i = 1; i <= n; i++) {update(a[i], 1);ans += i - sum(a[i]);  // 求逆序对}cout << ans << endl;return 0;
}

P3531 [POI2012]LIT-Letters(求逆序对)相关推荐

  1. szu 寒训第二天 树状数组 二维树状数组详解,以及树状数组扩展应用【求逆序对,以及动态第k小数】

    树状数组(Binary Index Tree) 树状数组可以解决可以转化为前缀和问题的问题 这是一类用以解决动态前缀和的问题 (有点像线段树简版) 1.对于 a1 + a2 + a3 + - + an ...

  2. Tido 习题-二叉树-树状数组求逆序对

    这里给大家提供一个全新的求逆序对的方法 是通过树状数组来实现的 题目描述   样例输入 Copy 5 2 3 1 5 4 样例输出 Copy 3 提示       #include<iostre ...

  3. codevs1688 求逆序对(权值线段树)

    1688 求逆序对  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果 题目描述 Description 给定一个序列a1,a2,-,an,如 ...

  4. 归并排序模板(附求逆序对)

    逆序对满足两个条件, i < j 和 ai > aj 归并可以求逆序对, 因为是按顺序加入, 所以右区间加入的时候, 左区间的数满足 i < j, 然后左边还没有加入的数肯定比当前的 ...

  5. hust1347(归并排序求逆序对)

    题意: 给出一个数列,你要对这个数列的数字进行k次交换操作,使得交换之后的数列逆序对虽少. 思路: 求原数列的逆序对,再和k比就行了.求逆序对要用归并排序,因为树状数组开不下. 代码: #includ ...

  6. 树状数组求逆序对_区间和的个数(树状数组)

    327. 区间和的个数 给定一个整数数组 nums,返回区间和在 [lower, upper] 之间的个数,包含 lower 和 upper. 区间和 S(i, j) 表示在 nums 中,位置从 i ...

  7. 用不同的姿势求逆序对(复习篇)

    用不同的姿势求逆序对(复习篇) 文章目录 用不同的姿势求逆序对(复习篇) 前言 讲解 归并排序 树状数组 线段树 题目 思路 代码 归并排序求逆序对 树状数组求逆序对 线段树求逆序对 历届试题 小朋友 ...

  8. CodeForces - 1417E XOR Inverse(字典树求逆序对+分治)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a,现在要求选出一个 x,将 a 中的每个元素都异或之后得到一个新的数列 b,要求数列 b 的逆序对最小,问最小的逆序对是多少,x 该如何选择 ...

  9. 信息竞赛进阶指南--归并排序求逆序对

    // 归并排序求逆序对 void merge(int l, int mid, int r) {// 合并a[l~mid]与a[mid+1~r]// a是待排序数组, b是临时数组, cnt是逆序对个数 ...

最新文章

  1. 面试都在问的微服务,一文带你彻底搞懂!
  2. Android中文API(115)——AudioFormat
  3. matlab input函数学习
  4. 中国油气装备行业发展状况与投资前景咨询报告2022-2028年版
  5. N-Gram的数据结构
  6. Kudu1.1.0 、 Kudu1.2.0 Kudu1.3.0的版本信息异同比较
  7. Python(18)-字典dictionary、集合
  8. php自定义tcp协议,如何实现自定义协议?
  9. win10鼠标指针修改
  10. c语言交通处罚管理系统刘,交通处罚单管理系统(C程序设计)修改版
  11. 【写博客常用】Word文档中怎么插入分隔线
  12. 计算机配件价格上涨,显卡涨价风声再起 PC配件涨价什么时候是个头
  13. ybt1373 鱼塘钓鱼
  14. 基于aspect的情感分析综述 论文翻译笔记 A Survey on Aspect-Based Sentiment Analysis: Tasks, Methods, and Challenges
  15. 谷歌是如何以简洁赢取用户的
  16. windows 调试若干知识
  17. React Native与原生的图片交互问题
  18. IxEngine开发笔记
  19. Python3的桌面程序开发利器:Eric6的环境搭建、使用
  20. 位图文件, JPG格式,PNG格式

热门文章

  1. [architecture]-Armv8 Cryptographic Extension介绍
  2. 使用 ZwUnmapViewOfSection 卸载并替换内存镜像
  3. 深入分析H2数据库控制台中无需身份验证的RCE漏洞
  4. 别再问Cloudflare CDN 漏洞是怎么被利用的啦!这篇文就来告诉你
  5. 透露抖音、腾讯、阿里、美团招开发岗位硬核面试题,轻轻松松收到offer
  6. 【PAT乙级】1082 射击比赛 (20 分)
  7. 【PAT乙级】1047 编程团体赛 (20 分)
  8. ActiveMQ介绍
  9. Java的List遍历
  10. python最大分词_python正向最大匹配分词和逆向最大匹配分词的实例