基于s值建立线段树
从左到右 对于i 利用线段树维护 [1,i-1] 范围内 s值比s[i]小的元素中c值最小的是多少 再从右到左跑一遍
似乎dp也可以写 只是复杂度要高许多
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 0x3f3f3f3f3f3f3f3f
struct node
{
int l;
int r;
ll val;
};
map <ll,int> mp;
node tree[2][12010];
ll s[3010],c[3010],pre[3010],lft[3010],rgt[3010];
int n,len;
void pushup(int id,int cur)
{
tree[id][cur].val=min(tree[id][2*cur].val,tree[id][2*cur+1].val);
return;
}
void build(int id,int l,int r,int cur)
{
int m;
tree[id][cur].l=l;
tree[id][cur].r=r;
tree[id][cur].val=N;
if(l==r) return;
m=(l+r)/2;
build(id,l,m,2*cur);
build(id,m+1,r,2*cur+1);
return;
}
ll query(int id,int pl,int pr,int cur)
{
ll res;
if(pl<=tree[id][cur].l&&tree[id][cur].r<=pr)
{
return tree[id][cur].val;
}
res=N;
if(pl<=tree[id][2*cur].r) res=min(res,query(id,pl,pr,2*cur));
if(pr>=tree[id][2*cur+1].l) res=min(res,query(id,pl,pr,2*cur+1));
return res;
}
void update(int id,int tar,ll val,int cur)
{
if(tree[id][cur].l==tree[id][cur].r)
{
tree[id][cur].val=min(tree[id][cur].val,val);
return;
}
if(tar<=tree[id][2*cur].r) update(id,tar,val,2*cur);
else update(id,tar,val,2*cur+1);
pushup(id,cur);
return;
}
int main()
{
ll minn;
int i;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%lld",&s[i]);
pre[i]=s[i];
}
for(i=1;i<=n;i++)
{
scanf("%lld",&c[i]);
}
sort(pre+1,pre+n+1);
len=unique(pre+1,pre+n+1)-pre-1;
for(i=1;i<=len;i++)
{
mp[pre[i]]=i;
}
build(0,1,len,1);
memset(lft,0x3f,sizeof(lft));
for(i=1;i<=n;i++)
{
if(mp[s[i]]-1>=1)
{
lft[i]=query(0,1,mp[s[i]]-1,1);
}
update(0,mp[s[i]],c[i],1);
}
build(1,1,len,1);
memset(rgt,0x3f,sizeof(rgt));
for(i=n;i>=1;i--)
{
if(mp[s[i]]+1<=len)
{
rgt[i]=query(1,mp[s[i]]+1,len,1);
}
update(1,mp[s[i]],c[i],1);
}
minn=N;
for(i=1;i<=n;i++)
{
minn=min(minn,lft[i]+c[i]+rgt[i]);
}
if(minn==N) printf("-1\n");
else printf("%lld\n",minn);
return 0;
}