BZOJ 1563 NOI2009 诗人小G 四边形不等式

题目大意:玩具装箱,然而指数变成了 p ( p10 )

首先我们需要证明决策单调
由于数死早,还是戳这里吧

知道决策单调之后怎么办呢?
由于是1D1D,所以不能分治了

每个决策点能决策的区间一定是连续的一段
并且随着决策点的右移 这个区间也在不断右移

g[j] 表示决策点 j 能贡献的最左侧的位置
然后我们开一个栈来维护当前存在贡献的贡献点
那么显然 stack[i] 的贡献区间是 [g[stack[i]],g[stack[i+1]]1]
每新来一个点,首先在栈中二分找到最优决策点
然后将所有满足
f[stack[top]]+W(stack[top],g[stack[top]])>f[i]+W(i,g[stack[top]])
的栈顶弹掉
然后二分找到最左侧的位置 pos 满足
f[stack[top]]+W(stack[top],pos)>f[i]+W(i,pos)
那么这个 pos 就是 g[i] ,如果能找到这个 pos ,就将 i 压栈

由于数字可能过大因此要用long double代替long long进行计算

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
#define LIMIT 1000000000000000000ll
using namespace std;
typedef long double ld;
int n,l,p;
int sum[M],g[M],stack[M],top;
ld f[M];
long double Slow_Power(long double x,int y)
{
    long double re=1;
    for(int i=1;i<=y;i++)
        re*=x;
    return re;
}
int Get_Len()
{
    static char s[40];
    scanf("%s",s+1);
    return strlen(s+1);
}
int Get_Pos(int x)
{
    int l=1,r=top;
    while(r-l>1)
    {
        int mid=l+r>>1;
        if( g[stack[mid]]<=x )
            l=mid;
        else
            r=mid;
    }
    return g[stack[r]]<=x?r:l;
}
ld F(int j,int i)
{
    return f[j]+Slow_Power(fabs(sum[i]-sum[j]+(i-j-1)-l),p);
}
int Get_G(int x,int y)
{
    int l=max(g[x],y)+1,r=n+1;
    while(r-l>1)
    {
        int mid=l+r>>1;
        if( F(y,mid) < F(x,mid) )
            r=mid;
        else
            l=mid;
    }
    if(l==r) return r;
    return F(y,l) < F(x,l) ? l : r ;
}
int main()
{
    int T,i;
    for(cin>>T;T;T--)
    {
        cin>>n>>l>>p;
        for(i=1;i<=n;i++)
            sum[i]=sum[i-1]+Get_Len();
        g[0]=1;stack[top=1]=0;
        for(i=1;i<=n;i++)
        {
            int pos=stack[Get_Pos(i)];
            f[i]=F(pos,i);
            while( g[stack[top]]>i && F(i,g[stack[top]]) < F(stack[top],g[stack[top]]) )
                stack[top--]=0;
            pos=Get_G(stack[top],i);
            if(pos!=n+1)
            {
                stack[++top]=i;
                g[i]=pos;
            }
        }
        if(f[n]-0.5>LIMIT)
            puts("Too hard to arrange");
        else
            cout<<(long long)(f[n]+0.5)<<endl;
        puts("--------------------");
    }
    return 0;
}

你可能感兴趣的:(bzoj,四边形不等式,BZOJ1563,NOI2009,决策单调)