先设 fi 为选位置i时的最优答案为多少,写出一个 O(n2) 的DP,
发现这个问题实质是:在位置i之前的所有的j,保证 pj<pi ,以P为关键字所组成的单调递减的栈,求单调栈中所有位置的 fj 的最小值,
这就是一道线段树维护单调栈的板题,
以 pi 作为下标,i作为值,每次查询线段树中,下标为1~ pi 的所有数所组成的单调栈,在把当前的数以 pi 作为下标,i作为值,插入到线段树中,
【技巧】线段树维护区间单调栈
复杂度: O(nlog(n)2) ;
考虑优化,我们发现,每次新加入的数的值是递增的,那么就是说,如果这个点加入到当前区间,那么在这个点之前的点都不会出现在单调栈中,
根据这个特性,在每个点维护一个单调栈表示,当前点的左区间的所有大于rmx的点所组成的单调栈,
如果新加入的点在区间右侧,那么这个单调栈肯定会被弹空,
如果在在左侧,加入这个点后的单调栈与之前的相比,原来的单调栈中,位置在这个点之前的点都不见了,变成了以这个新点打头,而原单调栈中,位置在这个新点之后的点都还在,
我们发现这个可以用一个单调栈来维护,
那么就每个区间维护一个栈,不过这个栈与实际的单调栈是刚好反过来的,
这样,每个点只会进栈 log(n) 次,出栈 log(n) 次,
复杂度: O(nlog(n))
这个是 O(nlog(n)2) 的普通做法,下边的是针对这题优化过的 O(nlog(n)) 的做法,
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define max(q,w) ((q)<(w)?(w):(q))
#define SD(q) ((q)==(b[b[q].fa].r))
using namespace std;
const int N=200500,INF=1e9;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans;
int f[N];
int a[N],a1[N];
bool Ansz[N];
struct qqww
{
int lv,mi,mx;
}b[N*4];
int Pmx;
int min(int q,int w){return q >1;
build(l,t,e*2);
build(t+1,r,e*2+1);
}
int find(int l,int r,int e,int l1,int r1,int P)
{
if(b[e].mxreturn 1e9;
if(l==r)
{
Pmx=max(Pmx,b[e].mx);
if(b[e].mx
return 1e9;
return b[e].mi;
}
int t=(l+r)>>1;
if(l1<=l&&r<=r1)
{
if(P>=b[e*2+1].mx)return find(l,t,e*2,l1,r1,P);
int ans=find(t+1,r,e*2+1,l1,r1,P);
ans=min(ans,b[e].lv);
Pmx=max(Pmx,b[e].mx);
return ans;
}
if(r1<=t)return find(l,t,e*2,l1,r1,P);
else if(treturn find(t+1,r,e*2+1,l1,r1,P);
else
{
int ans=find(t+1,r,e*2+1,t+1,r1,P);
return min(ans,find(l,t,e*2,l1,t,Pmx));
}
}
void change(int l,int r,int e,int l1,int l2)
{
if(l==r)
{
b[e].mi=f[l2];
b[e].mx=l2;
return;
}
int t=(l+r)>>1;
if(l1<=t)
{
change(l,t,e*2,l1,l2);
}
else
{
change(t+1,r,e*2+1,l1,l2);
}
Pmx=0;
b[e].lv=find(l,t,e*2,l,t,b[e*2+1].mx);
b[e].mx=max(b[e*2].mx,b[e*2+1].mx);
b[e].mi=min(b[e*2].mi,b[e*2+1].mi);
}
int main()
{
freopen("knows.in","r",stdin);
freopen("knows.out","w",stdout);
int q,w;
read(n);
fo(i,1,n)read(a[i]);
fo(i,1,n)read(a1[i]);
q=0;
fod(i,n,1)
{
if(a[i]>q)Ansz[i]=1;
q=max(q,a[i]);
}
build(0,n,1);
fo(i,1,n)
{
Pmx=0;
f[i]=find(0,n,1,0,a[i],0)+a1[i];
change(0,n,1,a[i],i);
}
ans=1e9;
fo(i,1,n)if(Ansz[i])ans=min(ans,f[i]);
printf("%d\n",ans);
return 0;
}
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define max(q,w) ((q)<(w)?(w):(q))
#define min(q,w) ((q)>(w)?(w):(q))
#define SD(q) ((q)==(b[b[q].fa].r))
using namespace std;
const int N=200500,INF=1e9;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans;
int f[N],a[N],a1[N];
bool Ansz[N];
struct qqww
{
int lv,mi,mx,A;
}b[N*3];
int B[15*N][3],B0;
int Pmx;
void build(int l,int r,int e)
{
if(l!=0)b[e].lv=b[e].mi=1e9;
else b[e].A=++B0;
if(l==r)return;
int t=(l+r)>>1;
build(l,t,e*2);
build(t+1,r,e*2+1);
}
int find(int l,int r,int e,int l1,int r1,int P)
{
if(b[e].mxreturn 1e9;
if(l==r)
{
Pmx=max(Pmx,b[e].mx);
if(b[e].mx
return 1e9;
return b[e].mi;
}
int t=(l+r)>>1;
if(l1<=l&&r<=r1)
{
if(P>=b[e*2+1].mx)return find(l,t,e*2,l1,r1,P);
int ans=find(t+1,r,e*2+1,l1,r1,P);
ans=min(ans,B[b[e].A][2]);
Pmx=max(Pmx,b[e].mx);
return ans;
}
if(r1<=t)return find(l,t,e*2,l1,r1,P);
else if(treturn find(t+1,r,e*2+1,l1,r1,P);
else
{
int ans=find(t+1,r,e*2+1,t+1,r1,P);
int ans1=find(l,t,e*2,l1,t,Pmx);
return min(ans,ans1);
}
}
void change(int l,int r,int e,int l1,int l2)
{
if(l==r)
{
b[e].mi=f[l2];
b[e].mx=l2;
return;
}
int t=(l+r)>>1;
if(l1<=t)
{
change(l,t,e*2,l1,l2);
for(;b[e].A&&B[b[e].A][1]0]);
B[++B0][0]=b[e].A;B[B0][2]=min(f[l2],B[b[e].A][2]);
b[e].A=B0;B[B0][1]=l1;
}
else
{
change(t+1,r,e*2+1,l1,l2);
b[e].A=0;
}
b[e].mx=max(b[e*2].mx,b[e*2+1].mx);
b[e].mi=min(b[e*2].mi,b[e*2+1].mi);
}
int main()
{
int q,w;
read(n);
fo(i,1,n)read(a[i]);
fo(i,1,n)read(a1[i]);
q=0;
fod(i,n,1)
{
if(a[i]>q)Ansz[i]=1;
q=max(q,a[i]);
}
build(0,n,1);
B[0][2]=1e9;
fo(i,1,n)
{
Pmx=0;
f[i]=find(0,n,1,0,a[i],0)+a1[i];
change(0,n,1,a[i],i);
}
ans=1e9;
fo(i,1,n)if(Ansz[i])ans=min(ans,f[i]);
printf("%d\n",ans);
return 0;
}