1380D 1900的题
题意:给你两个数组,长度为n的a【】,和长度为m的b【】,保证数组内的数字不同,你能进行的操作有两个,
op1:选择连续的k个数字,花费x,使其删除
op2:选择连续的两个数字,花费y,删除其中更小的一个
通过这些操作使数组a变为数组b,如果不能则输出-1,如果能则输出最小的花费
思路:这题要注意的主要是爆int范围一直wa6 。
首先的思路要清晰,对于数组a变为数组b首先要具备的条件就是b是a的子序列。
然后对数组a进行拆分,假设要删去的为(l, r),l和r是不需要删去的,要删去的是(l,r)包含的数
那么对这段长度为len=r-l-1的数组进行讨论,
当这段的最大值不在两端的时候,必须要用一次op1,不然无法删去最大的那个数,如果len<k,那就打印-1
其次,对于op1和op2的贪心,花费x删除k个数,花费y删1个数,
当x<y*k时,表明op1相对于op2是更优的,所以先尽可能的使用op1再使用op2
反之,全部使用op2
具体实现可看代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <stack>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
#define rep(i, a, n) for(int i = a; i <= n; i++)
#define per(i, a, n) for(int i = n; i >= a; i--)
#define IOS std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define fopen freopen("file.in","r",stdin);freopen("file.out","w",stdout);
#define fclose fclose(stdin);fclose(stdout);
#define PI 3.14159265358979323846
const int inf = 1e9;
const ll onf = 1e18;
const int maxn = 2e5+10;
inline ll read(){
ll x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
std::vector<ll> v;
ll a[maxn], b[maxn];
ll n, m, x, k, y;
ll solve(ll l, ll r){
if(r-l==1) return 0;
ll mx;ll z = 0;
for(ll i = l; i <= r; i++){
if(a[i]>z){
z=a[i];mx=i;
}
}
ll tmp = 0, len = r-l-1;
if(mx>l&&mx<r){
if(len<k) return -1;
tmp += x;
len -= k;
}
if(x<k*y){
ll cnt = len/k;
tmp += cnt*x+(len-cnt*k)*y;
}else {
tmp += len*y;
}
return tmp;
}
signed main(){
n=read(), m=read(), x=read(), k=read(), y=read();
rep(i,1,n) a[i]=read();
rep(i,1,m) b[i]=read();
ll pos = 1;
rep(i,1,n){
if(a[i]==b[pos]) v.push_back(i), pos++;
}
if(pos!=m+1){printf("-1\n");return 0;}
ll res = 0;
for(ll i = 0; i <= m; i++){
ll tmp;
if(i==0) {
tmp = solve(0,v[0]);
// printf("%d ", tmp);
if(tmp!=-1) res+=tmp;
else {printf("-1\n");return 0;}
}else if(i==m) {
tmp = solve(v[m-1],n+1);
// printf("%d ", tmp);
if(tmp!=-1) res+=tmp;
else {printf("-1\n");return 0;}
}else {
tmp = solve(v[i-1],v[i]);
// printf("%d ", tmp);
if(tmp!=-1) res+=tmp;
else {printf("-1\n");return 0;}
}
}
printf("%lld\n", res);
return 0;
}