BZOJ 1563 NOI2009 诗人小G 四边形不等式
2015-06-18 12:38
369 查看
题目大意:玩具装箱,然而指数变成了pp(p≤10p\leq10)
首先我们需要证明决策单调
由于数死早,还是戳这里吧
知道决策单调之后怎么办呢?
由于是1D1D,所以不能分治了
每个决策点能决策的区间一定是连续的一段
并且随着决策点的右移 这个区间也在不断右移
令g[j]g[j]表示决策点jj能贡献的最左侧的位置
然后我们开一个栈来维护当前存在贡献的贡献点
那么显然stack[i]stack[i]的贡献区间是[g[stack[i]],g[stack[i+1]]−1][g[stack[i]],g[stack[i+1]]-1]
每新来一个点,首先在栈中二分找到最优决策点
然后将所有满足
f[stack[top]]+W(stack[top],g[stack[top]])>f[i]+W(i,g[stack[top]])f[stack[top]]+W(stack[top],g[stack[top]]) > f[i]+W(i,g[stack[top]])
的栈顶弹掉
然后二分找到最左侧的位置pospos满足
f[stack[top]]+W(stack[top],pos)>f[i]+W(i,pos)f[stack[top]]+W(stack[top],pos) > f[i]+W(i,pos)
那么这个pospos就是g[i]g[i],如果能找到这个pospos,就将ii压栈
由于数字可能过大因此要用long double代替long long进行计算
首先我们需要证明决策单调
由于数死早,还是戳这里吧
知道决策单调之后怎么办呢?
由于是1D1D,所以不能分治了
每个决策点能决策的区间一定是连续的一段
并且随着决策点的右移 这个区间也在不断右移
令g[j]g[j]表示决策点jj能贡献的最左侧的位置
然后我们开一个栈来维护当前存在贡献的贡献点
那么显然stack[i]stack[i]的贡献区间是[g[stack[i]],g[stack[i+1]]−1][g[stack[i]],g[stack[i+1]]-1]
每新来一个点,首先在栈中二分找到最优决策点
然后将所有满足
f[stack[top]]+W(stack[top],g[stack[top]])>f[i]+W(i,g[stack[top]])f[stack[top]]+W(stack[top],g[stack[top]]) > f[i]+W(i,g[stack[top]])
的栈顶弹掉
然后二分找到最左侧的位置pospos满足
f[stack[top]]+W(stack[top],pos)>f[i]+W(i,pos)f[stack[top]]+W(stack[top],pos) > f[i]+W(i,pos)
那么这个pospos就是g[i]g[i],如果能找到这个pospos,就将ii压栈
由于数字可能过大因此要用long double代替long long进行计算
[code]#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 100100 #define LIMIT 1000000000000000000ll using namespace std; typedef long double ld; int n,l,p; int sum[M],g[M],stack[M],top; ld f[M]; long double Slow_Power(long double x,int y) { long double re=1; for(int i=1;i<=y;i++) re*=x; return re; } int Get_Len() { static char s[40]; scanf("%s",s+1); return strlen(s+1); } int Get_Pos(int x) { int l=1,r=top; while(r-l>1) { int mid=l+r>>1; if( g[stack[mid]]<=x ) l=mid; else r=mid; } return g[stack[r]]<=x?r:l; } ld F(int j,int i) { return f[j]+Slow_Power(fabs(sum[i]-sum[j]+(i-j-1)-l),p); } int Get_G(int x,int y) { int l=max(g[x],y)+1,r=n+1; while(r-l>1) { int mid=l+r>>1; if( F(y,mid) < F(x,mid) ) r=mid; else l=mid; } if(l==r) return r; return F(y,l) < F(x,l) ? l : r ; } int main() { int T,i; for(cin>>T;T;T--) { cin>>n>>l>>p; for(i=1;i<=n;i++) sum[i]=sum[i-1]+Get_Len(); g[0]=1;stack[top=1]=0; for(i=1;i<=n;i++) { int pos=stack[Get_Pos(i)]; f[i]=F(pos,i); while( g[stack[top]]>i && F(i,g[stack[top]]) < F(stack[top],g[stack[top]]) ) stack[top--]=0; pos=Get_G(stack[top],i); if(pos!=n+1) { stack[++top]=i; g[i]=pos; } } if(f -0.5>LIMIT) puts("Too hard to arrange"); else cout<<(long long)(f +0.5)<<endl; puts("--------------------"); } return 0; }
相关文章推荐
- 学习过程
- scala调用java api
- Ubuntu 下mysql常用的操作语句
- 排序--折半插入
- ORACLE锁机制深入理解
- ExtJs自学教程(1):从一切API开始
- Google对员工到底有多好?
- mongo学习-基础知识
- 《疯狂的站长》读后感2
- arduino 红外遥控小车
- CF Soldier and Cards
- Git 命令
- nodeName、nodeValue 以及 nodeType
- .NET跨平台:在Ubuntu上用自己编译的dnx运行ASP.NET 5示例程序
- cgteamwork 观感
- 网站如何接入支付宝(转)
- git使用之如何将github库下载到本地与如何将代码上传github
- 排序---直接插入
- Unix环境之文件IO
- java——hello word