您的位置:首页 > 其它

bzoj1563 [NOI2009]诗人小G

2013-04-22 16:06 621 查看
决策单调优化的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

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define maxn 120000
#define mxll 1e18
using namespace std;
long double f[maxn];
long double sum[maxn];
int q[maxn],ll[maxn],rr[maxn],len[maxn];
int n,m,limit,p,cas,head,tail;

long double px(long double a)
{
if (a<0) a=-a;
long double mid=1;
for (int i=1;i<=p;i++) mid*=a;
return mid;
}
long double clac(int i,int j)
{
return f[j]+px(sum[i]-sum[j]+i-j-1-limit);
}

void update(int i)
{
while (ll[tail]>i&&clac(ll[tail],q[tail])>clac(ll[tail],i)) rr[tail-1]=rr[tail--];
int l=ll[tail],r=rr[tail],pos=r+1;
while (l<=r)
{
int mid=(l+r)>>1;
if (clac(mid,q[tail])>clac(mid,i)) r=mid-1,pos=mid;
else l=mid+1;
}
if (pos<=rr[tail])
{
ll[tail+1]=pos;
rr[tail+1]=rr[tail];
rr[tail]=pos-1;
q[++tail]=i;
}
}

void solve()
{
head=tail=1;
ll[head]=1; rr[head]=n;
for (int i=1;i<=n;i++)
{
if (i>rr[head]) head++;
f[i]=clac(i,q[head]);
update(i);
}
}

void init()
{
scanf("%d%d%d",&n,&limit,&p);
char s[100];
for (int i=1;i<=n;i++)
{
scanf("%s",s);
len[i]=strlen(s);
sum[i]=sum[i-1]+len[i];
}
}

void write()
{
if (f
>mxll) printf("Too hard to arrange\n");
else printf("%lld\n",(long long)f
);
printf("--------------------\n");
}

int main()
{
//freopen("poet10.in","r",stdin);
scanf("%d",&cas);
while (cas--)
{
init();
solve();
write();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: