1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include <bits/stdc++.h> using namespace std; const int N=20010,M=1000010,R=20000; int ls[M],rs[M],rt[N],idx,n,K,b[N],f[N][110],s[M],c[N],RT[N],Id; struct dline{ int k,b; dline(){} dline(int k,int b):k(k),b(b){} int at(int x){return k*x+b;} }a[N<<1]; void copy(int x,int y){ls[x]=ls[y],rs[x]=rs[y],s[x]=s[y];} int build(int p,int l,int r){ p=++idx; if(l==r)return p; int mid=(l+r)>>1; ls[p]=build(p,l,mid); rs[p]=build(p,mid+1,r); return p; } void Upd(int &p,int l,int r,int x){ if(!p)return (void)(p=++idx,s[p]=x); int &y=s[p],mid=(l+r)>>1; int t=a[x].at(mid)-a[y].at(mid); if(t<0)swap(x,y); int tl=a[x].at(l)-a[y].at(l),tr=a[x].at(r)-a[y].at(r); if(tl<0)Upd(ls[p],l,mid,x); if(tr<0)Upd(rs[p],mid+1,r,x); } int upd(int p,int l,int r,int x){ ++idx,copy(idx,p);p=idx; int &y=s[p],mid=(l+r)>>1; int t=a[x].at(mid)-a[y].at(mid); if(t<0)swap(x,y); int tl=a[x].at(l)-a[y].at(l),tr=a[x].at(r)-a[y].at(r); if(tl<0)ls[p]=upd(ls[p],l,mid,x); if(tr<0)rs[p]=upd(rs[p],mid+1,r,x); return p; } int merge(int p,int q,int l,int r){ if(!p||!q)return p+q; if(l==r){ int t=a[s[p]].at(l)-a[s[q]].at(l); if(t<0)swap(s[p],s[q]); return p; } int mid=(l+r)>>1; Upd(p,l,r,s[q]); ls[p]=merge(ls[p],ls[q],l,mid); rs[p]=merge(rs[p],rs[q],mid+1,r); return p; } int query(int p,int l,int r,int x){ if(l==r)return a[s[p]].at(x); int mid=(l+r)>>1; return min(a[s[p]].at(x),(mid>=x?query(ls[p],l,mid,x):query(rs[p],mid+1,r,x))); } void clear(){for(int i=1;i<=n;i++)c[i]=0;} void add(int x,int y){for(int i=x;i>=1;i-=(i&-i))c[i]=max(c[i],y);} int Query(int x){int cnt=0;for(int i=x;i<=n;i+=(i&-i))cnt=max(cnt,c[i]);return cnt;} int id[N],tot; int main(){ scanf("%d%d",&n,&K); memset(f,0x3f,sizeof(f)); for(int i=1;i<=n;i++)scanf("%d",&b[i]); for(int i=1,t=0;i<=n;i++)t=max(t,b[i]),f[i][1]=i*t; a[0]=dline(0,2e9); Id=n; for(int i=2;i<=K;i++){ rt[0]=build(1,1,n); for(int j=i;j<=n;j++){ add(j,b[j]); a[j-1]=dline(b[j],f[j-1][i-1]-(j-1)*b[j]); a[++Id]=dline(-(j-1),f[j-1][i-1]); Upd(RT[j-1],1,R,Id); id[++tot]=j-1; rt[tot]=upd(rt[tot-1],1,n,j-1); int l=1,r=tot; while(l<r){ int mid=(l+r)>>1; if(Query(id[mid]+1)<=b[j])r=mid; else l=mid+1; } if(l<tot){ for(int k=l+1;k<=tot;k++)RT[id[l]]=merge(RT[id[l]],RT[id[k]],1,R); tot=l; a[id[l]]=dline(b[j],query(RT[id[l]],1,R,b[j])); rt[tot]=upd(rt[tot-1],1,n,id[l]); } f[j][i]=query(rt[tot],1,n,j); } clear(); for(int j=0;j<=idx;j++)s[j]=ls[j]=rs[j]=0; for(int j=1;j<=n;j++)rt[j]=RT[j]=id[j]=0; idx=tot=0;Id=n; } printf("%d\n",f[n][K]); return 0; }
|