P3531 [POI2012]LIT-Letters(求逆序对)
生活随笔
收集整理的這篇文章主要介紹了
P3531 [POI2012]LIT-Letters(求逆序对)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目傳送門: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(求逆序对)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Xcode 新项目删除 storyboa
- 下一篇: P1744 采购特价商品(SPFA求最短