1. 程式人生 > >BZOJ_1563_[NOI2009]詩人小G_決策單調性

BZOJ_1563_[NOI2009]詩人小G_決策單調性

esp con algo pri 技術分享 r++ div 方案 句子

BZOJ_1563_[NOI2009]詩人小G_決策單調性

Description

技術分享圖片

Input

技術分享圖片

Output

對於每組數據,若最小的不協調度不超過1018,則第一行一個數表示不協調度若最小的不協調度超過1018,則輸出"Too hard to arrange"(不包含引號)。每個輸出後面加"--------------------"

Sample Input

4
4 9 3
brysj,
hhrhl.
yqqlm,
gsycl.
4 9 2
brysj,
hhrhl.
yqqlm,
gsycl.
1 1005 6
poet
1 1004 6
poet

Sample Output

108
--------------------
32
--------------------
Too hard to arrange
--------------------
1000000000000000000
--------------------

【樣例說明】
前兩組輸入數據中每行的實際長度均為6,後兩組輸入數據每行的實際長度均為4。一個排版方案中每行相鄰兩個句子之間的空格也算在這行的長度中(可參見樣例中第二組數據)。每行末尾沒有空格。

HINT

總共10個測試點,數據範圍滿足:

測試點 T N L P
1 ≤10 ≤18 ≤100 ≤5
2 ≤10 ≤2000 ≤60000 ≤10

3 ≤10 ≤2000 ≤60000 ≤10
4 ≤5 ≤100000 ≤200 ≤10
5 ≤5 ≤100000 ≤200 ≤10
6 ≤5 ≤100000 ≤3000000 2
7 ≤5 ≤100000 ≤3000000 2
8 ≤5 ≤100000 ≤3000000 ≤10
9 ≤5 ≤100000 ≤3000000 ≤10
10 ≤5 ≤100000 ≤3000000 ≤10
所有測試點中均滿足句子長度不超過30。


設F[i]表示處理完前i個單詞的最小不協調度。s[i]為前綴和+i。L=L+1。

$F[i]=F[j]+(s[i]-s[j]-L)^P$

假設有j1<j2<i1<i2.

j2轉移i1比j1轉移i1優,j1轉移i2比j2轉移i2優。

那麽$F[j2]+(s[i1]-s[j2]-L)^P\le F[j1]+(s[i1]-s[j1]-L)^P$

$F[j1]+(s[i2]-s[j1]-L)^P\le F[j2]+(s[i2]-s[j2]-L)^P$

那麽$(s[i1]-s[j2]-L)^P+(s[i2]-s[j1]-L)^P\le (s[i1]-s[j1]-L)^P+(s[i2]-s[j2]-L)^P$

相當於$(X)^P+(Y)^P\le (X-D)^P+(Y+D)^P$ (D=s[j1]-s[j2])顯然不成立。

於是DP滿足決策單調性。

用一個單調隊列維護區間染色,每次二分即可。

註意答案可能爆longlong,double卡精,直接longdouble沒問題,當然也可以double判無解再用longlong輸出。

代碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
typedef double f2;
#define N 100050
inline char nc() {
    static char buf[100000],*p1,*p2;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int rd() {
    int x=0; char s=nc();
    while(s<‘0‘||s>‘9‘) s=nc();
    while(s>=‘0‘&&s<=‘9‘) x=(x<<3)+(x<<1)+s-‘0‘,s=nc();
    return x;
}
int rv() {
    char s=nc(); int re=0;
    while(s<33||s>127) s=nc();
    while(s>=33&&s<=127) re++,s=nc();
    return re;
}
struct A {
    int l,r,p;
}Q[N];
int n,L,P,a[N],from[N],s[N];
f2 f[N];
f2 qp(f2 x,int y) {
    f2 re=1; if(x<0) x=-x;
    for(;y;y>>=1,x=x*x) if(y&1) re=re*x; return re;
}
ll qpp(ll x,int y) {
    ll re=1; if(x<0) x=-x;
    for(;y;y>>=1,x=x*x) if(y&1) re=re*x; return re;
}
#define Y(j,i) (f[j]+qp(s[i]-s[j]-L,P))
int find(const A &a,int x) {
    int l=a.l,r=a.r+1;
    while(l<r) {
        int mid=(l+r)>>1;
        if(Y(x,mid)>Y(a.p,mid)) l=mid+1;
        else r=mid;
    }
    return l;
}
ll get(int p) {
    if(p<n/7) return f[p];
    // if(p<700) return f[p];
    return get(from[p])+qpp(s[p]-s[from[p]]-L,P);
}
void work() {
    n=rd(); L=rd()+1; P=rd();
    register int i;
    int l,r;
    for(i=1;i<=n;i++) {
        s[i]=s[i-1]+rv()+1; f[i]=1e20;
    }
    l=r=0; Q[r++]=(A){0,n,0};
    for(i=1;i<=n;i++) {
        while(l<r&&Q[l].r<i) l++;
        f[i]=Y(Q[l].p,i); from[i]=Q[l].p;
        if(Y(i,n)<=Y(Q[r-1].p,n)) {
            while(l<r&&Y(i,Q[r-1].l)<=Y(Q[r-1].p,Q[r-1].l)) r--;
            if(l==r) Q[r++]=(A){i,n,i};
            else {
                int x=find(Q[r-1],i);
                Q[r-1].r=x-1;
                Q[r++]=(A){x,n,i};
            }
        }
    }
    if(f[n]>1e18) puts("Too hard to arrange");
    else {
        printf("%lld\n",get(n));
    }
}
int main() {
    int T=rd();
    while(T--) {
        work();
        puts("--------------------");
    }
}

BZOJ_1563_[NOI2009]詩人小G_決策單調性