标准的1d/1d形式,具有决策单调性,二分栈优化nlogn。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define maxn 100050 #define inf 1000000000000000000LL using namespace std; int t,n,l,p,s[maxn],top=0,sum[maxn],g[maxn]; char sj[maxn]; long double dp[maxn]; long double calc(int i,int j) { long double ret=sum[i]-sum[j]+i-j-l-1;ret=fabs(ret);long double ans=1.0; for (int i=1;i<=p;i++) ans=ans*ret; return ans+dp[j]; } int get_pos(int x) { int l=1,r=top,ans=-1; while (l<=r) { int mid=(l+r)>>1; if (g[s[mid]]<=x) {ans=s[mid];l=mid+1;} else r=mid-1; } return ans; } int get_di(int l,int r,int x,int y) { int ans; while (l<=r) { int mid=(l+r)>>1; if (calc(mid,x)<calc(mid,y)) {ans=mid;l=mid+1;} else r=mid-1; } return ans+1; } void work() { memset(dp,0,sizeof(dp));memset(sum,0,sizeof(sum));memset(g,0,sizeof(g)); scanf("%d%d%d",&n,&l,&p); for (int i=1;i<=n;i++) {scanf("%s",sj);sum[i]=sum[i-1]+strlen(sj);} top=1;s[1]=0;g[0]=1; for (int i=1;i<=n;i++) { int ret=get_pos(i);dp[i]=calc(i,ret); while (g[s[top]]>i && calc(g[s[top]],s[top])>calc(g[s[top]],i)) s[top--]=0; int pos=get_di(max(g[s[top]],i),n,s[top],i); if (pos==n+1) continue; s[++top]=i;g[s[top]]=pos; } if (dp[n]-0.5>inf) printf("Too hard to arrange\n"); else printf("%lld\n",(long long)dp[n]); printf("--------------------\n"); } int main() { scanf("%d",&t); for (int i=1;i<=t;i++) work(); return 0; }