日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P3531 [POI2012]LIT-Letters(求逆序对)

發布時間:2025/3/20 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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(求逆序对)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。