P9572
题意比较清楚,不再阐述。
以下简要称输入的两数组为
思路
考虑第一问如何作答。
观察到,LCS(最长公共子序列)中的元素,必须都出现在
由题意,
考虑第二问。
为了方便,我们将两数组“离散化”。用样例
处理完之后就好做了。我们发现,
使用 map 时要卡常数。
文字太抽象,建议看代码理解。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define db double
#define mkp make_pair
#define pb push_back
#define P pair<int,int>
#define _ 0
const int N=1e6+10,mod=1e9+7,MOD=1e9+123,inf=1e18;
int T=1,n,m,c1,c2,a[N],b[N],ans1,vis[N],val[N],lst[N],c[N],vis2[N];
vector<int> vec[N];
unordered_map<int,int> mp;
void solve(){
cin>>n>>m>>c1>>c2;
for(int i=1;i<=n;i++){
cin>>a[i];
vis[a[i]]=1;
}
int ans1=m,cnt=0;
for(int i=1;i<=m;i++){
cin>>b[i];
if(!vis[b[i]]) {
ans1--;
continue;
}
cnt++;
if(!vis2[b[i]]) lst[b[i]]=cnt,vis2[b[i]]=1;
val[cnt]=lst[b[i]];
}
m=cnt,cnt=0;
for(int i=1;i<=n;i++){
if(lst[a[i]]){
a[++cnt]=lst[a[i]];
}
}
n=cnt;
for(int i=1;i<=n;i++){
vec[a[i]].pb(i);
}
int ans2=0,now=0;
for(int i=1;i<=m;i++){
if(mp[val[i]]>=(int)vec[val[i]].size()){
ans2++,mp.clear(),now=0;
}
int &mpp=mp[val[i]];
while(vec[val[i]][mpp]<now&&mpp<(int)vec[val[i]].size()) mpp++;
if(mp[val[i]]>=(int)vec[val[i]].size()){
ans2++,mp.clear(),now=vec[val[i]][mp[val[i]]],mp[val[i]]++;
}
else{
if(vec[val[i]][mp[val[i]]]>now){
now=vec[val[i]][mp[val[i]]];
mp[val[i]]++;
}
else ans2++,mp.clear(),now=vec[val[i]][mp[val[i]]],mp[val[i]]++;
}
}
cout<<c1*ans1<<" "<<c2*(ans2+1);
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false),cin.tie(0);
while(T--){
solve();
}
return ~~(0^_^0);
}
好像代码也很丑陋呢。。