2013寒假练习 1011 Maximum Sum II
2013-02-18 09:18
661 查看
地址:http://acm.bit.edu.cn/mod/programming/view.php?a=497
题意:子段长度不超过k的最大子段和。
看似简单题,序号又靠前,结果就给虐了T T
一开始妄图用和最大子段和差不多的方法做,最后才发现算法不对。
正解如下:
sum[i]表示前i个数之和(特别的sum[0]=0),问题转化为找一个最小的sum[j](i-k=<j<i),因为sum[i]-sum[j]即使从j+1到i这个子段的和,故对于当前i,问题转化为找一个最小的sum[j](i-k=<j<i)。直接二重循环会TLE,我们要想办法用O(1)的时间找出最小的sum[j],这实际上是一个移动窗口最值问题,参考/article/3902817.html,可以用单调队列实现。具体对于这题就是每次将sum[i-1]入队,同时通过删除队尾元素保持队列递增;也将队头的无用元素删掉,找最小值时永远是队头元素最小。具体参看以上链接。
题意:子段长度不超过k的最大子段和。
看似简单题,序号又靠前,结果就给虐了T T
一开始妄图用和最大子段和差不多的方法做,最后才发现算法不对。
正解如下:
sum[i]表示前i个数之和(特别的sum[0]=0),问题转化为找一个最小的sum[j](i-k=<j<i),因为sum[i]-sum[j]即使从j+1到i这个子段的和,故对于当前i,问题转化为找一个最小的sum[j](i-k=<j<i)。直接二重循环会TLE,我们要想办法用O(1)的时间找出最小的sum[j],这实际上是一个移动窗口最值问题,参考/article/3902817.html,可以用单调队列实现。具体对于这题就是每次将sum[i-1]入队,同时通过删除队尾元素保持队列递增;也将队头的无用元素删掉,找最小值时永远是队头元素最小。具体参看以上链接。
#include<iostream> #include<deque> using namespace std; int sum[50005],ans; int main() { int t,n,k,i,temp; scanf("%d",&t); while(t--) { sum[0]=0; scanf("%d%d",&n,&k); for(i=1;i<=n;i++) { scanf("%d",&temp); sum[i]=sum[i-1]+temp; } deque<int>q; ans=sum[1]; for(i=1;i<=n;i++) { while(!q.empty()&&sum[i-1]<=sum[q.back()]) q.pop_back(); while(!q.empty()&&q.front()<i-k) q.pop_front(); q.push_back(i-1); if(sum[i]-sum[q.front()]>ans) ans=sum[i]-sum[q.front()]; } printf("%d\n",ans); } return 0; }
相关文章推荐
- BIT 1011 Maximum Sum II
- 2013寒假练习 1057 SUM
- 算法分析课每周练习 Binary Tree Maximum Path Sum
- 2013寒假练习 1054 Largest prime factor
- 2013寒假练习 1055 The Euler function
- BIT寒假练习-2013__1010:Maximum Sum
- 2013寒假练习 1006:The most frequent number
- 2013寒假练习 1008:Putting Apples
- LeetCode 编程练习 - Two Sum II - Input array is sorted学习心得
- 2013寒假练习 1002: Roman numerals
- 2013寒假练习 1033 Squares
- 2013寒假练习 1000:a+b
- 2013寒假练习 1009:Number Sequence
- BIT寒假练习-2013__1012:导弹防御问题
- 2013寒假练习 1015:Edit Distance
- 2013寒假练习 1021:Pascal's Travels
- 2013寒假练习 1022 Mondriaan's Dream
- 2013寒假练习 1046 Leftmost Digit
- BIT寒假练习-2013__1000:a+b
- 2013寒假练习 1001:Average Numbers