题意:
n个战士排成一排,分别有个武力值ai。你有两种法术,一个是火球(花费x个法力,消灭连续k个战士),一个是激怒(花费y个法力,选择相邻两个战士,武力值大的会消灭武力值小的)。求最后留下的战士排列成bi需要的最小法力花费
思路:
因为每个数都不同,所以肯定是划分成多个区间,对每个区间进行操作。
如果当前区间的长度
:
①区间最大值大于左右端点,那么无解。因为无法消去最大值。
②区间最大值小于等于左右端点,消费就是
如果当前区间的长度
:
①区间最大值大于左右端点,那么必须花费一个
,来把最大值消掉。如果火球更优,那么答案就是
。可以用最大值把
个战士消掉,然后用火球消去连续的 k 。一定有解。如果激怒更优,那么答案就是
②区间最大值小于左右端点,不是必须花费
,则就直接判断哪种方式更优,同上。
代码有点细节
code
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define ll long long
int a[man],b[man];
signed main() {
int n,m;scanf("%d%d",&n,&m);
int x,k,y;scanf("%d%d%d",&x,&k,&y);
for(int i = 1;i <= n;++i)scanf("%d",a+i);
for(int i = 1;i <= m;++i)scanf("%d",b+i);
a[n+1] = b[m+1] = -1;
ll ans = 0;
for(int i = 1,j = 0;i <= m+1;++i){
int l = j+1,r = j+1,len = 0,maxx =-1;
while(r<=n+1&&a[r]!=b[i])maxx = max(maxx,a[r]),r++;
if(r>n+1){ans = -1;break;}
len = r - l;
if(len<k){
if(maxx>max(a[l-1],a[r])){ans = -1;break;}
else ans += 1ll*y*len;
}else{
if(maxx>max(a[l-1],a[r])){
ans += 1ll*x;
len -= k;
if(x<1ll*k*y)ans += 1ll*(len/k)*x + 1ll*(len%k)*y;
else ans += 1ll*y*len;
}else{
if(x<1ll*k*y)ans += 1ll*(len/k)*x + 1ll*(len%k)*y;
else ans += 1ll*y*len;
}
}
if(a[r]!=b[i])j = r + 1;
else j = r;
}
printf("%lld\n",ans);
return 0;
}