bzoj1563 [NOI2009]诗人小G
决策单调优化的1D1D动规,比较经典的题,链接一下byvoid大神的博客http://www.byvoid.com/blog/noi-2009-poet
博客里说的很清楚了。这个题主要是利用了四边形不等式证出了决策的单调性,这样我们可以二分不停地更新决策区间,这样效率nlogn可以ac。
由于这个题比较奇葩,要求大于10^18的输出Too hard to arrange,所以过程中需要保存大于long long的数,所以我们用long double 保存中间量,这样最后再转成long long 就行了。
poet
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define maxn 120000 7 #define mxll 1e18 8 using namespace std; 9 long double f[maxn]; 10 long double sum[maxn]; 11 int q[maxn],ll[maxn],rr[maxn],len[maxn]; 12 int n,m,limit,p,cas,head,tail; 13 14 long double px(long double a) 15 { 16 if (a<0) a=-a; 17 long double mid=1; 18 for (int i=1;i<=p;i++) mid*=a; 19 return mid; 20 } 21 long double clac(int i,int j) 22 { 23 return f[j]+px(sum[i]-sum[j]+i-j-1-limit); 24 } 25 26 void update(int i) 27 { 28 while (ll[tail]>i&&clac(ll[tail],q[tail])>clac(ll[tail],i)) rr[tail-1]=rr[tail--]; 29 int l=ll[tail],r=rr[tail],pos=r+1; 30 while (l<=r) 31 { 32 int mid=(l+r)>>1; 33 if (clac(mid,q[tail])>clac(mid,i)) r=mid-1,pos=mid; 34 else l=mid+1; 35 } 36 if (pos<=rr[tail]) 37 { 38 ll[tail+1]=pos; 39 rr[tail+1]=rr[tail]; 40 rr[tail]=pos-1; 41 q[++tail]=i; 42 } 43 } 44 45 void solve() 46 { 47 head=tail=1; 48 ll[head]=1; rr[head]=n; 49 for (int i=1;i<=n;i++) 50 { 51 if (i>rr[head]) head++; 52 f[i]=clac(i,q[head]); 53 update(i); 54 } 55 } 56 57 void init() 58 { 59 scanf("%d%d%d",&n,&limit,&p); 60 char s[100]; 61 for (int i=1;i<=n;i++) 62 { 63 scanf("%s",s); 64 len[i]=strlen(s); 65 sum[i]=sum[i-1]+len[i]; 66 } 67 } 68 69 void write() 70 { 71 if (f[n]>mxll) printf("Too hard to arrange\n"); 72 else printf("%lld\n",(long long)f[n]); 73 printf("--------------------\n"); 74 } 75 76 int main() 77 { 78 //freopen("poet10.in","r",stdin); 79 scanf("%d",&cas); 80 while (cas--) 81 { 82 init(); 83 solve(); 84 write(); 85 } 86 return 0; 87 }
AC without art, no better than WA !