题解:P13788 「CZOI-R6」Permutation and Subsequence
P13788 题解:
主要思路:
- 用数组
c 存储b 排列中的每个数在a 排列中的位置。
::::info[为什么是
- 我们设
dp_{b_i} 为以b_i 结尾的在a 中出现过的子序列的数量,于是不难写出这样的状态转移方程:
其中
于是就有了这样的
#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int N=1e6+7;
int n;
int a[N],b[N],c[N],dp[N];
int32_t main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
c[a[i]]=i;
}
for(int i=1;i<=n;i++){
cin>>b[i];
}
int sum=n;
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(c[b[i]]-1==c[b[j]]){
dp[b[i]]=dp[b[j]]+1;
sum+=dp[b[i]];
}
}
}
cout<<sum;
return 0;
}
交上去,获得
那么问题又来了,怎么消掉内部循环?
我们不难发现,内部循环遍历时,只有一个
::::info[为什么是
知道了这些,我们就可以写出状态转移方程了!
代码实现:
定义一个变量存储最终答案,再用上文的状态转移方程求和就可以了。
~其实上文那一大坨放代码里也挺清晰的。~
AC Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int N=1e6+7;
int n;
int a[N],b[N],c[N],dp[N];
int32_t main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
c[a[i]]=i;//存储位置
}
for(int i=1;i<=n;i++){
cin>>b[i];
}
int sum=0;//存最终答案
for(int i=1;i<=n;i++){
dp[b[i]]=dp[a[c[b[i]]-1]]+1;//状态转移方程
sum+=dp[b[i]];
}
cout<<sum;
return 0;//完结撒花!!!
}
感谢阅读。
写题解不易,留个赞再走吧!!!