考虑怎样删除区间 [ l , r ] [l,r] [l,r]内的战士
考虑一种无脑的做法,让区间 [ l , r ] [l,r] [l,r]一直使用狂暴,剩下一个和 a l − 1 a_l-1 al−1或 a r + 1 a_{r+1} ar+1狂暴就能全部消除
但如果区间中的最大数比 a l − 1 a_{l-1} al−1和 a r + 1 a_{r+1} ar+1都大,那么最后它是无法消除的,我们称这种数字为特殊数字
所以应该先用火球术把这种比两边大的数字消掉才行
此时如果 ( r − l + 1 ) < k (r-l+1)<k (r−l+1)<k,不足以使用一次火球则无解,其余都可以消除
这里需要分两种情况
①.当 y ∗ k < = x y*k<=x y∗k<=x时,狂暴比较划算
所以在消除特殊数字的同时还要最小化火球术的次数
当区间中没有特殊数字时,一直狂暴即可,代价 ( r − l + 1 ) ∗ y (r-l+1)*y (r−l+1)∗y
否则,一直在最大数字周围使用狂暴知道只剩 k k k个元素,用一次火球即可消除干净
②.当 y ∗ k > x y*k>x y∗k>x时,火球比较划算
所以在消除特殊数字的同时还要最大化火球术的次数
令 z = ( r − l + 1 ) % k z=(r-l+1)\%k z=(r−l+1)%k,显然可以先用狂暴消掉任意 z z z个数字,然后一直用火球术即可消干净
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e6+10;
int n,m,t,x,y,k,flag = 1;
int a[maxn],b[maxn],mx[maxn][22],lg[maxn];
unordered_map<int,int>ma;
int get(int l,int r)
{
int k = lg[r-l+1];
return max( mx[l][k],mx[r-(1<<k)+1][k] );
}
int solve(int l,int r)
{
if( l>r ) return 0ll;
int w = get(l,r);
if( w>max( a[l-1],a[r+1] ) && (r-l+1)<k ) flag = 0;
if( y*k<=x )
{
if( w<max( a[l-1],a[r+1] ) ) return y*(r-l+1);
else if( w>max( a[l-1],a[r+1]) ) return ( r-l+1-k )*y+x;
}
else
{
int z = (r-l+1)%k;
return (r-l+1)/k*x+z*y;
}
}
signed main()
{
ios::sync_with_stdio( false ); cin.tie( 0 ); cout.tie( 0 );
for(int i=2;i<=1000000;i++) lg[i] = lg[i>>1]+1;
ma.clear();
cin >> n >> m >> x >> k >> y;
for(int i=1;i<=n;i++) cin >> a[i], ma[a[i]] = i, mx[i][0] = a[i];
for(int j=1;j<=20;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
mx[i][j] = max( mx[i][j-1],mx[i+(1<<(j-1))][j-1] );
int las = 0, ans = 0;
for(int i=1;i<=m;i++)
{
cin >> b[i];
int x = ma[b[i]];
if( !ma.count( b[i] ) ) flag = 0;
else
{
if( x<las ) flag = 0;
else las = x;
}
}
b[0] = 0;
for(int i=1;i<=m;i++)
{
if( i==1 )
{
if( a[1]==b[1] ) continue;
ans += solve( 1,ma[b[1]]-1 );
}
else
ans += solve( ma[b[i-1]]+1,ma[b[i]]-1 );
}
if( a[n]!=b[m] ) ans += solve( ma[b[m]]+1,n );
if( flag==0 ) ans = -1;
cout << ans << endl;
}