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 }

 

转载于:https://www.cnblogs.com/zig-zag/archive/2013/04/22/3035704.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值