1. 程式人生 > 實用技巧 >CF1380D.Berserk And Fireball(思維)

CF1380D.Berserk And Fireball(思維)

/*
 *CF1380D.Berserk And Fireball
 *n個戰士站成一排,分別有武力值ai。
 *你有兩種法術:火球和激怒。
 *火球可以消耗x個法力,消滅連續k個戰士。
 *激怒可以消耗y個法力,選擇相鄰的兩個戰士,武力值大的會消滅武力值小的
 *求最後留下的戰士和陣列b一樣所需要的最小法力花費
 *題解:
 *劃分為多個區間
 *如果當前區間的長度len<k
 *區間最大值大於左右端點,則無解,因為無法消去最大值
 *區間最大值小於左右端點,消費就是len*y
 *如果當前區間的長度len>=k
 *區間最大值大於左右端點,那必須花費一個x來把最大值消掉。
 */
#include
<bits/stdc++.h> using namespace std; const int maxn=2e5+100; typedef long long ll; int a[maxn]; int b[maxn]; ll n,m,x,k,y; int main () { scanf("%lld%lld%lld%lld%lld",&n,&m,&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,Max=-1; while (r<=n+1&&a[r]!=b[i]) Max=max(Max,a[r]),r++; if (r>n+1) { ans=-1;break; } len=r-l; if (len<k) {
if (Max>max(a[l-1],a[r])) { ans=-1;break; } else { ans+=y*len; } } else { if (Max>max(a[l-1],a[r])) { ans+=x; len-=k; if (x<k*y) ans+=(len/k)*x+(len%k)*y; else ans+=y*len; } else { if (x<k*y) ans+=(len/k)*x+(len%k)*y; else ans+=y*len; } } if (a[r]!=b[i]) j=r+1; else j=r; } printf("%lld\n",ans); }