决策单调性优化
BZOJ1563
#include <cstdio> #include <cmath> #include <cstring> #include <iostream> #define LDB long double using namespace std; struct data{ int po,l,r; }sta[100010]; char st[101]; LDB a[100010],dp[100010]; int p,top,n,but; LDB stad; LDB qpow(LDB bas,int powe){ LDB ret=1; for (;powe;bas*=bas){ if (powe&1) ret*=bas; powe=powe>>1; } return(ret); } LDB F(int po,int tar){ return(qpow(fabs(a[tar]-a[po-1]+tar-po-stad),p)+dp[po-1]); } void edi(int po){ if (F(sta[top].po,n)<F(po,n)) return; while (top>=but&&F(sta[top].po,sta[top].l)>F(po,sta[top].l)) top--; if (top<but){ sta[++top].po=po; sta[top].l=po+1;sta[top].r=n; }else{ int l=max(sta[top].l,po),r=n; while (l!=r){ int mid=(l+r)>>1; if (F(sta[top].po,mid)>F(po,mid)) r=mid;else l=mid+1; } sta[++top].po=po; sta[top-1].r=l-1; sta[top].l=l;sta[top].r=n; } } int main(){ int T; scanf("%d",&T); while (T--){ scanf("%d%Lf%d",&n,&stad,&p); for (int i=1;i<=n;i++){ scanf("%s",&st); a[i]=strlen(st); a[i]+=a[i-1]; dp[i]=2*1e18; } top=but=1; sta[top].po=1;sta[top].l=1;sta[top].r=n; dp[1]=qpow(fabs(a[1]-stad),p); for (int i=2;i<=n;i++){ sta[but].l=i; while (top>=but&&sta[but].r<i) but++; dp[i]=F(sta[but].po,i); dp[i]=min(dp[i-1]+qpow(fabs(a[i]-a[i-1]-stad),p),dp[i]); edi(i); } if (dp[n]>1e18) printf("Too hard to arrange\n");else printf("%.0Lf\n",dp[n]); printf("--------------------\n"); } }
____________________________________
BZOJ2216
#include <cstdio> #include <iostream> #include <cmath> #define LDB long double using namespace std; struct data{ int po,l,r; }sta[500001]; int a[500001],top,but,n,ans[500001]; LDB f(int j,int i){ return(a[j]+(sqrt(fabs((LDB)i-(LDB)j)))-a[i]); } void push(int po){ if (f(sta[top].po,n)>f(po,n)) return; while (top>=but&&f(sta[top].po,sta[top].l)<f(po,sta[top].l)) top--; if (top<but){ sta[++top].po=po; sta[top].l=1;sta[top].r=n; }else{ int l=max(sta[top].l,po),r=sta[top].r; while (l<r){ int mid=(l+r)>>1; if (f(po,mid)>f(sta[top].po,mid)) r=mid;else l=mid+1; } sta[++top].po=po; sta[top-1].r=l-1; sta[top].l=l;sta[top].r=n; } } void work(){ top=but=1; sta[1].po=1;sta[1].l=1;sta[1].r=n; for (int i=2;i<=n;i++){ sta[but].l=i+1; while (top>=but&&sta[but].r<i) but++; ans[i]=max(ans[i],(int)(ceil(f(sta[but].po,i))+0.001)); push(i); } } int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); work(); for (int i=1;i<=n/2;i++){ int t=a[i];a[i]=a[n-i+1];a[n-i+1]=t; t=ans[i];ans[i]=ans[n-i+1];ans[n-i+1]=t; } work(); for (int i=n;i>=1;i--) printf("%d\n",ans[i]); }