动态规划练习5
2017-07-27 13:08
169 查看
[b]复仇滚木[/b]
题目描述:
lw的狂暴药水经常到处乱洒!有一棵树因为被lw狂暴过很多次了,它变异了!它给自己取名为复仇滚木,它要找lw报仇(什么仇什么怨)。lw听到了这个消息,立马着手准备去教训它。他想从他的n把斧头中选取一些连续的斧头,但最多选m把。每把斧头都有一个威力值,但因为有些斧头很久没磨了,所以可能有些斧头威力值为负。lw想知道他能获得的威力值最大为多少。
输入格式:
第一行两个数,分别为n和m,接下来n行,每行一个数,即这个斧头的威力值。
输出格式:
一个数,即最大威力值。
样例输入:log.in
4 2
8
-2
3
7
样例输出:log.out
10(选3和7)
数据范围:
对于30%的数据,n,m<=1000
对于100%的数据,n,m<=100000
[b]题解:[/b]
[b]大水题。。。[/b]
[b]用s[i]表示前缀和,f[i]表示i为区间右端点时的可以取得的最大值。[/b]
[b]f[i]=s[i]-min{s[k]|i-m≤k≤i}[/b]
[b]把i之前m个s[]组成一个队列。在这m个s[]中,如果i<j,且s[i]>s[j]那么s[i]肯定用不到,因为s[i]比s[j]先出队,s[i]又比s[j]大所以肯定用不到它。所以可以把该队列的元素满足:S1<S2<S3<……<Sk(因为不一定有m个元素,所以用k表示)[/b]
[b]这样的话取最小值也是O(1)的,每进一个元素从右边开始比较,如果比它大就删掉(满足刚才的性质),当然加了元素之后还要判断是否队列超过m个元素,超过就把左边的删除。摊还分析一下,每个元素进队一次,出队一次,所以总复杂度是O(n)的。[/b]
题目描述:
lw的狂暴药水经常到处乱洒!有一棵树因为被lw狂暴过很多次了,它变异了!它给自己取名为复仇滚木,它要找lw报仇(什么仇什么怨)。lw听到了这个消息,立马着手准备去教训它。他想从他的n把斧头中选取一些连续的斧头,但最多选m把。每把斧头都有一个威力值,但因为有些斧头很久没磨了,所以可能有些斧头威力值为负。lw想知道他能获得的威力值最大为多少。
输入格式:
第一行两个数,分别为n和m,接下来n行,每行一个数,即这个斧头的威力值。
输出格式:
一个数,即最大威力值。
4 2
8
-2
3
7
样例输出:log.out
10(选3和7)
数据范围:
对于30%的数据,n,m<=1000
对于100%的数据,n,m<=100000
[b]题解:[/b]
[b]大水题。。。[/b]
[b]用s[i]表示前缀和,f[i]表示i为区间右端点时的可以取得的最大值。[/b]
[b]f[i]=s[i]-min{s[k]|i-m≤k≤i}[/b]
[b]把i之前m个s[]组成一个队列。在这m个s[]中,如果i<j,且s[i]>s[j]那么s[i]肯定用不到,因为s[i]比s[j]先出队,s[i]又比s[j]大所以肯定用不到它。所以可以把该队列的元素满足:S1<S2<S3<……<Sk(因为不一定有m个元素,所以用k表示)[/b]
[b]这样的话取最小值也是O(1)的,每进一个元素从右边开始比较,如果比它大就删掉(满足刚才的性质),当然加了元素之后还要判断是否队列超过m个元素,超过就把左边的删除。摊还分析一下,每个元素进队一次,出队一次,所以总复杂度是O(n)的。[/b]
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define inf (2000000000) using namespace std; typedef long long lol; lol q[100001],head,tail=1,n,m,a[100001],ans=-inf; lol gi() { lol ans=0,f=1; char i=getchar(); while(i<'0'||i>'9'){if(i=='-')f=-1;i=getchar();} while(i>='0'&&i<='9'){ans=ans*10+i-'0';i=getchar();} return ans*f; } int main() { freopen("log.in","r",stdin); freopen("log.out","w",stdout); lol i,j; n=gi();m=gi(); for(i=1;i<=n;i++) { a[i]=gi(); a[i]+=a[i-1]; } for(i=1;i<=n;i++) { while(i-q[head]>m)head++; ans=max(ans,a[i]-a[q[head]]); while(tail-1>=head&&a[q[tail-1]]>a[i])tail--; q[tail++]=i; } printf("%lld",ans); return 0; }
相关文章推荐
- 2016.4.2 动态规划练习--讲课整理
- 最长递增、递减子序列(导弹拦截问题)动态规划练习
- hud上的动态规划练习
- 编程练习二(动态规划)
- 编程练习-动态规划(最长公共子序列LCS)
- 动态规划练习一 14:怪盗基德的滑翔翼
- 动态规划练习-1(最长上升子序列)
- 动态规划练习05:吃糖果
- 动态规划练习--29(合唱队形)
- 动态规划练习一:n条直线的交点个数
- 动态规划练习1 [导弹拦截]
- 算法练习(7) —— 动态规划 Strange Printer
- 数据结构 练习 16-动态规划
- 树型动态规划练习总结
- poj 1458 小白算法练习 Common Subsequence 动态规划
- 动态规划练习-2(最大子矩阵)
- 动态规划练习06:登山
- 动态规划练习——采药
- 动态规划练习 9
- 动态规划练习(1)