奥法之劫 题解
这里是
我们先从一个朴素的
设
那么我们可以进行一步步优化到
先关注
这些代价不仅和当前
我们发现代价是不好计算的。随着
换一种思路,我们可以考虑每个
也就是说,我们要找到对于每一个
具体而言,我们可以在
那么每次我想选一个
这样我们砍掉了计算区间贡献的
再想想,由于
但此时,我们的转移点还是不确定,并且没有考虑
对于
没错,这里的影响就只和
其实我们
我们设
其中
我们发现
这样最小化了能够最小化的部分,也统计了代价。
最后注意几点:
-
为了保证最后答案能够统计到,要在
n+1 的位置插一个极大值。 -
如果存在
a_i\neq b_j 对于任意的j ,那么它不能参与统计答案,但必须要参与代价以及sum 的计算。 -
其实~f 和sum 数组根本没必要开。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
const int N=5e6+9;
const ll INF=1e18;
inline int read(){
int res=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
res=(res<<1)+(res<<3)+ch-'0';
ch=getchar();
}
return res*f;
}
int n,a[N],b[N],Q[N],m,pos[N];
ll f[N],g[N],cost[N],p[N],sum;
int main()
{
// freopen("hs.in","r",stdin);
// freopen("offa.out","w",stdout);
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) p[i]=read();
n++,a[n]=n;
m=read();
for(int i=1;i<=m;i++) b[i]=read();
for(int i=1;i<=m;i++) pos[b[i]]=i;
m++,b[m]=n,pos[n]=m;
for(int i=1;i<N;i++) g[i]=INF;
for (int i=1,j=1;i<=n;++i)
{
if(b[j]<i) j++;
Q[i]=j;
}
ll tmp=0;
for (int i=1;i<=n;i++)
{
int j=pos[a[i]];
if(j)
{
if(g[j-1]>=INF) f[i]=INF;
else f[i]=g[j-1]+cost[j]+sum;
}
if(p[i]>=0) cost[Q[a[i]]]+=p[i];
else sum+=p[i];
if(j&&f[i]<INF) g[j]=min(g[j],f[i]-sum);
}
if (f[n]<INF) printf("%lld",f[n]);
else puts("Impossible");
return 0;
}