【NOIP2012模拟11.1】塔(加强)
2016-08-18 15:32
351 查看
题目
玩完骰子游戏之后,你已经不满足于骰子游戏了,你要玩更高级的游戏。今天你瞄准了下述的好玩的游戏:
首先是主角:塔。你有N座塔一列排开。每座塔各自有高度,有可能相等。
这个游戏就不需要地图了。
你每次可以选择相邻的两座塔合并在一起,即这两座塔的高度叠加后变成了同一座塔。然后原本分别与这两座塔相邻的塔变得与这座新的塔相邻。
你的目标是在使用最少的操作次数在游戏的最后获得一列塔,这些塔的高度从左到右形成一个不下降的数列。
分析
这是到结论题。。。结论一:每个块越小越好。
so,设fi表示处理完了i的最小操作次数。再设hi表示最优情况下的gi的i所在的塔的高度最小值。
转移为:
fi=min(fi,fj+i−j−1(gj<=sum(j+1...i)))
这是O(n2)的。
我们想办法优化它,
首先,因为fi+1>=fi+1
结论二,当我们枚举j从后往前搜,当高度合法,就是最优的答案,也就可以break。
但是,这还是超时了。
我们打个单调队列。
#include <cmath> #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> const long long maxlongint=2147483647; const long long mo=1000000007; const long long N=1000025; using namespace std; long long f ,a ,n,maxa,ans=maxlongint,sum ,g ,d ; int main() { memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); scanf("%lld",&n); f[0]=g[0]=0; long long l,r; d[l=r=1]=0; for(long long i=1;i<=n;i++) scanf("%lld",&a[i]),maxa=max(a[i],maxa),sum[i]=sum[i-1]+a[i]; for(long long i=1;i<=n;i++) { while(g[d[l+1]]+sum[d[l+1]]<=sum[i] && l<r) l++; long long sigma=sum[i]-sum[d[l]]; f[i]=f[d[l]]+i-d[l]-1; g[i]=sigma; while(g[d[r]]+sum[d[r]]>=sum[i]+g[i] && l<=r) r--; d[++r]=i; } printf("%lld",f ); }
相关文章推荐
- jzoj3083. 【NOIP2012模拟11.1】塔(加强)
- 【NOIP2012模拟11.1】塔(加强)
- JZOJ3083. 【NOIP2012模拟11.1】塔(加强)
- jzoj3082. 【NOIP2012模拟11.1】骰子游戏
- {题解}[jzoj3083]【NOIP2012模拟11.1】塔
- 【NOIP2012模拟11.1】骰子游戏
- JZOJ3082. 【NOIP2012模拟11.1】骰子游戏
- JZOJ2937. 【NOIP2012模拟8.9】监听还原(2017.9B组)
- 【NOIP2012模拟11.5】小A 的作业
- CQOI2012 BZOJ2669 【NOIP2016提高A组模拟8.15】Garden
- 高中纪中OJ3078. 【备战NOIP2012图论专项模拟试题】无线通讯网
- 3078. 【备战NOIP2012图论专项模拟试题】无线通讯网 (Standard IO)
- 【NOIP2012模拟10.25】剪草
- 【NOIP2012模拟8.9】逐个击破
- 【2012noip模拟】最长路径(path)
- 【模拟】【noip2012普及组】寻宝
- JZOJ2938. 【NOIP2012模拟8.9】分割田地
- 3079. 【备战NOIP2012图论专项模拟试题】砍树 (Standard IO)
- 【NOIP2012模拟10.25】剪草
- 【NOIP2014模拟11.1B组】吴传之火烧连营(tree)