BZOJ 1563 诗人小G

Posted on 2017-03-23 09:42  ziliuziliu  阅读(206)  评论(0编辑  收藏  举报

标准的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;
}