[单调栈][线段树]JZOJ 6305 最小值

Description

 

Input

Output

 

Sample Input

Sample 1:
5 0 0 1 10
9 9 5 2 6 

Sample 2:
100 1 1 1 1
18515 13638 5356 485 8646 14871 18955 6206 7630 14703 6786 15099 15960 17822 435 3233 9775 20340 12669 14079 1164 3329 3642 16094 4294 2462 18926 16887 17661 8416 18196 20799 15422 1943 13795 11165 21418 5646 7773 11921 14908 9305 3334 13677 5757 6875 15324 20940 10919 7703 14804 19536 13777 3500 4797 6658 19839 2962 19871 2668 16584 18204 19193 13887 20172 5323 11400 3381 14167 11494 14646 682 2333 11615 16430 6959 14652 19819 13504 20629 1202 17839 13863 4646 3607 14270 10575 6024 3583 16544 11898 1395 18535 12607 6929 736 2303 8950 20436 7050
 

Sample Output

Sample 1:
81

Sample 2:
263138765928780
 
 

Data Constraint

分析

我们发现,如果加入第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]);
}
View Code

 

posted @ 2019-08-19 07:38  Vagari  阅读(186)  评论(0编辑  收藏  举报