[单调栈][线段树]JZOJ 6305 最小值
分析
我们发现,如果加入第i位后,将会有一段j满足min[j,i]=a[i](也可能没有)
那么我们用单调栈维护这个东西(即min值变化点),两个变化点之间的f值是恒定的,然后最优答案从dp[li -1 ~ li-1 -1]中选择
#include <iostream> #include <cstdio> using namespace std; typedef long long ll; const ll Inf=2e18; const int N=2e5+10; int n; ll A,B,C,D,stk[N],t[4*N],a[N],f[N]; int top; ll F(ll x) {return A*x*x*x+B*x*x+C*x+D;} void Change(int x,int l,int r,int k) { if (l==r) { t[x]=f[k]; return; } int mid=l+r>>1; if (k<=mid) Change(x<<1,l,mid,k); if (mid<k) Change((x<<1)+1,mid+1,r,k); t[x]=max(t[x<<1],t[(x<<1)+1]); } ll Query(int x,int l,int r,int xl,int xr) { if (xr<l||r<xl||r<l) return -Inf; if (xl<=l&&r<=xr) return t[x]; int mid=l+r>>1; ll ans=-Inf; if (xl<=mid) ans=Query(x<<1,l,mid,xl,xr); if (mid<xr) ans=max(ans,Query((x<<1)+1,mid+1,r,xl,xr)); return ans; } int main() { freopen("min.in","r",stdin); freopen("min.out","w",stdout); scanf("%d%lld%lld%lld%lld",&n,&A,&B,&C,&D); for (int i=1;i<=n;i++) scanf("%lld",&a[i]),f[i]=-Inf; for (int i=1;i<4*N;i++) t[i]=-Inf; Change(1,0,n,0); for (int i=1;i<=n;i++) { while (top&&a[stk[top]]>=a[i]) top--; stk[++top]=i; for (int j=top;j;j--) f[i]=max(f[i],F(a[stk[j]])+Query(1,0,n,stk[j-1],stk[j]-1)); Change(1,0,n,i); } printf("%lld",f[n]); }
在日渐沉没的世界里,我发现了你。