可以发现,我们一定会选择
i
和
dpi=vi+maxi,j可以相邻dpj
这个dp可以用分治优化。考虑左边对右边的贡献,把每个位置按照 pi 递增的顺序加入,在左边维护一个 i 递减的单调栈用来更新答案【
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=200010,maxt=4000010,oo=2e9+1000;
int n,a[maxn],v[maxn],dp[maxn],mn[maxt],f[maxn],g[maxn],s1[maxn],s2[maxn];
int cmp(int x,int y)
{
return a[x]<a[y];
}
void modi(int u,int L,int R,int p,int x)
{
if (L==R)
{
mn[u]=x;
return;
}
int mid=(L+R)/2;
if (p<=mid) modi(u*2,L,mid,p,x);
else modi(u*2+1,mid+1,R,p,x);
mn[u]=min(mn[u*2],mn[u*2+1]);
}
int qry(int u,int L,int R,int l,int r)
{
if (l<=L&&R<=r) return mn[u];
int ret=oo,mid=(L+R)/2;
if (l<=mid) ret=min(ret,qry(u*2,L,mid,l,r));
if (r>mid) ret=min(ret,qry(u*2+1,mid+1,R,l,r));
return ret;
}
void solve(int l,int r)
{
if (l==r) return;
int mid=(l+r)/2,t1=0,t2=0;
solve(l,mid);
for (int i=l;i<=mid;i++) f[i]=i;
for (int i=mid+1;i<=r;i++) g[i]=i;
sort(f+l,f+mid+1,cmp);
sort(g+mid+1,g+r+1,cmp);
for (int i=l,j=mid+1;i<=mid||j<=r;)
if (i<=mid&&(j>r||a[f[i]]<a[g[j]]))
{
while (t1&&s1[t1]<f[i])
{
modi(1,0,n,a[s1[t1]],oo);
t1--;
}
s1[++t1]=f[i];
modi(1,0,n,a[f[i]],dp[f[i]]);
i++;
}
else
{
while (t2&&s2[t2]>g[j]) t2--;
dp[g[j]]=min(dp[g[j]],qry(1,0,n,t2?a[s2[t2]]+1:0,a[g[j]])+v[g[j]]);
s2[++t2]=g[j];
j++;
}
while (t1) modi(1,0,n,a[s1[t1--]],oo);
solve(mid+1,r);
}
void build(int u,int L,int R)
{
mn[u]=oo;
if (L==R) return;
int mid=(L+R)/2;
build(u*2,L,mid);
build(u*2+1,mid+1,R);
}
int main()
{
//freopen("i.in","r",stdin);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++) scanf("%d",&v[i]);
n++;
a[n]=n;
build(1,0,n);
for (int i=1;i<=n;i++) dp[i]=oo;
solve(0,n);
printf("%d\n",dp[n]);
}