[NOI2009] Poet G--Decision-Making Monotone Optimization dp

Keywords: Programming

Question: https://www.luogu.org/problemnew/show/P1912

Practice: First of all, the ordinary dp is easy to come up with, f [i] = Min {f [j] + cost (j + 1, i)} (j >= 1 & & J < i), the complexity is n^2.

But this problem can find that the decision is monotonic (that is, I F g[i] denotes the subscript when f[i] obtains the optimum, then g[i]>= g [j], i f I > j), the simple proof is to discuss the relationship between length and l.

The problem of satisfying the monotonicity of decision can be solved in nlogn time, maintaining a two-way queue, where there is a decision-making jurisdiction interval (i.e. the interval within which the decision is optimal at this time). The interval where the pop team first gets the coverage I when updating a certain position I is the I-point optimal decision. When inserting a new decision, it is more than the left-most point of the end of the queue jurisdiction, if more. Optimal POP Team tail continues to operate directly, otherwise in the current team tail jurisdiction area two points, find the new decision jurisdiction area, complexity because each point in and out of the team is only once O (n), so the complexity bottleneck is in the dichotomy, nlogn.

Note that the maximum value used in this problem is 1e36, and it can not stop directly when exploding long, because it is possible to add some string lengths closer to l but not explode long long, so long double is used in this problem.

Code:

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define ll long double
using namespace std;
const ll inf=1e18;
const int N=1e5+10;

struct jc{
    int l,r,ps;
    jc(){};
    jc(int l,int r,int ps):l(l),r(r),ps(ps){};
};
ll f[N],sum[N];
int n,l,p,a[N],ret[N];
char S[N][35];
deque<jc>q;

ll spow(ll x)
{
    x=fabs(x);ll res=1;
    if(x==0)return 0;
    for(int i=1;i<=p;i++)
        res=res*x;
    return res;
}
ll calc(int j,int i)
{return f[j]+spow(sum[i]-sum[j]+(i-j-1)-l);}
int bserch(int l,int r,int a,int b)
{
    l=max(l,b+1),r=max(r,b+1);
    int mid,res=r+1;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(calc(a,mid)>=calc(b,mid))res=mid,r=mid-1;
        else l=mid+1;
    }
    if(l<res&&calc(a,l)>=calc(b,l))res=l;
    if(r<res&&calc(a,r)>=calc(b,r))res=r;
    return res;
}
void dfs(int pos)
{
    int bf=ret[pos];
    if(bf)dfs(bf);
    for(int i=bf+1;i<=pos;i++)
    {
        if(i!=bf+1)putchar(' ');
        printf("%s",S[i]+1);
    }
    puts("");
}
int main()
{
    int T,L;
    scanf("%d",&T);
    while(T--)
    {
        f[0]=sum[0]=0;
        scanf("%d%d%d",&n,&l,&p);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",S[i]+1);
            a[i]=strlen(S[i]+1);
            sum[i]=sum[i-1]+a[i];
        }
        while(!q.empty())q.pop_back();
        q.push_front(jc(1,n,0));
        for(int i=1;i<=n;i++)
        {
            while(q.front().r<i)q.pop_front();
            ret[i]=q.front().ps,f[i]=calc(q.front().ps,i),L=n+1;
            while(!q.empty())
            {
                if(calc(q.back().ps,q.back().l)>=calc(i,q.back().l))L=min(L,q.back().l),q.pop_back();
                else break;
            }
            if(q.empty()||L<=i+1){q.push_back(jc(L,n,i));continue;}
            L=bserch(q.back().l,q.back().r,q.back().ps,i);
            if(L<=n)q.back().r=L-1,q.push_back(jc(L,n,i));
        }		
        if(f[n]>inf)puts("Too hard to arrange");
        else 
        {
            printf("%lld\n",(long long)f[n]);
            dfs(n);
        }
        puts("--------------------");
    }
}

 

Posted by Nukedesign on Sat, 26 Jan 2019 15:06:14 -0800