![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSP9EVTmZ0VapHZzIWa1cVYop0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2UTOzATNyQTM1EzMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
題意:
選擇一種排列,使得數組a和b有更多的相同子序列。
例如,例1:1 2 3 和 3 2 1 ;p可以為2 1 3;
是以排列為 a2 a1 a3 和 b2 b1 b3.
即 2 1 3 和 2 3 1; 此時 2 1 是相同子序列, 長度為2;
再例如 , 例2:
6
1 5 3 2 6 4
3 6 2 4 5 1
可以看成
1 3 2 4 5 6
3 2 4 1 6 5
第一個部分,可以排序得到
1 4 2 3
3 1 4 2
子序列長度為 4 - 1;(如果an != bn 是以每個部分的長度 最長為 每個子序列的長度 - 1, 如果an == bn , 每個部分的長度 最長為 每個子序列的長度, 則 每個an 可以看出一個部分)
if 部分的長度 == 1, 則 ans ++;
else ans += (部分的長度 - 1);
此時 ans = (4 - 1) + (2 - 1) = 4;
群置換代碼如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAX = 1e5 + 5;
int main() {
int T;
scanf("%d", &T);
while(T--) {
int N;
scanf("%d", &N);
int a[MAX],b[MAX],c[MAX];//c[]的作用是 幫助 找到每個部分的集合
bool vis[MAX] = {0};
for(int i = 1; i <= N; i++) {
scanf("%d", &a[i]);
c[a[i]] = i;
}
for(int i = 1; i <= N; i++) scanf("%d", &b[i]);
int ans = 0;
for(int i = 1; i <= N; i++) {
int t = 1;
if(!vis[a[i]]) {
int pos = a[i];
int x = b[i];
while(pos != x) {
vis[a[c[x]]] = 1;
x = b[c[x]];
t++;
}
if(t == 1) ans++;
else ans += (t - 1);
}
}
printf("%d\n", ans);
}
}
其實兩種做法隻是找集合的方法不一樣。
并查集的代碼如下
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAX = 1e5 + 5;
int a[MAX] , b[MAX];
int fa[MAX] , t[MAX];
void init(int n) {
for(int i = 0 ; i <= n ; i++) {
fa[i] = i;
t[i] = 1;
}
}
int find(int x) {
if(x != fa[x])
fa[x] = find(fa[x]);
return fa[x];
}
void Union(int x , int y) {
int xx = find(x);
int yy = find(y);
if(xx != yy) {
fa[x] = yy;
t[yy] += t[xx];
}
}
int main() {
int T;
scanf("%d" , &T);
while(T--) {
int N;
scanf("%d" , &N);
init(MAX);
for(int i = 0 ; i < N; i++) {
scanf("%d" , &a[i]);
}
for(int i = 0 ; i < N ; i++) {
scanf("%d" , &b[i]);
Union(a[i] , b[i]);
}
int ans = 0;
for(int i = 0 ; i < N ; i++) {
if(fa[a[i]] == a[i]) {
if(t[a[i]] == 1) {
ans++;
}
else {
ans += (t[a[i]] - 1);
}
}
}
printf("%d\n" , ans);
}
return 0;
}