/* 给定一个数组,切割成pre,suf,现在要移动这两个集合中的元素,使 Max(pre)<Min(suf),且移动代价最小 对问题进行转化:移动后长度为len的pre,必定包含[1,len] 所以枚举移动前pre的长度,再考虑每个移动后pre长度的对应的代价 第二步可用线段树优化,每个结点维护移动后长度为i的对应的代价,可以通过区间更新进行递推维护 求出每种pre的最小值,再求个最小值即可 */ #include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=200005; const ll INF=(1LL<<60)-1; int p[MAXN],a[MAXN]; ll mi[MAXN<<2],tag[MAXN<<2]; inline void push_up(int n) { mi[n]=min(mi[n<<1],mi[n<<1|1]); } inline void push_down(int n) { if(!tag[n])return; mi[n<<1]+=tag[n]; mi[n<<1|1]+=tag[n]; tag[n<<1]+=tag[n]; tag[n<<1|1]+=tag[n]; tag[n]=0; } void update(int ql,int qr,int v,int l,int r,int n) { if(ql==l && qr==r) { mi[n]+=v; tag[n]+=v; return; } push_down(n); int m=(l+r)/2; if(qr<=m)update(ql,qr,v,l,m,n<<1); else if(ql>m)update(ql,qr,v,m+1,r,n<<1|1); else { update(ql,m,v,l,m,n<<1); update(m+1,qr,v,m+1,r,n<<1|1); } push_up(n); } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&p[i]); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) update(p[i],n,a[i],0,n,1); ll res=INF; for(int i=1;i<n;i++) { update(p[i],n,-a[i],0,n,1); update(0,p[i]-1,a[i],0,n,1); res=min(res,mi[1]); } return 0*printf("%lld ",res); }