一个疑问

chin_chen 2009-01-19 10:16:36
给定一组数 例如:4, 2, 1, 5, 3 ;求在所有其子串(这个子串中的数必须是递增的)中,哪个子串里面所有的数之和最大?
给个例子:
1) 4
2) 2
3) 1
4) 5
5) 3
6) 4, 5
7) 2, 5
8) 2, 3
9) 1, 5
10) 1, 3
这些都是满足条件的子串,在这些子串中第6个子串( 4, 5)的数之和为9,那么它就是最大的。
之前,我曾想过用2叉排序树,做这个题目的,后来忘了怎么做的,不过这个题目好像又可以用动态规划思想来做,不知道哪位有什么高见没?请给出代码和思想以及负责度。谢谢!
...全文
81 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
FancyMouse 2009-01-19
  • 打赏
  • 举报
回复
俄……bbst是可以的,只是每个节点需要维护一个它和子树的dp值最大,那样就能做nlogn了
FancyMouse 2009-01-19
  • 打赏
  • 举报
回复
>算法可以进一步优化到O(n*logn)
求细节。这里单调队列不适用吧,因为会出现插中间的情况,单纯一个线形表做不到
  • 打赏
  • 举报
回复
是可以动态规划,其实和“最长单调递增子序列”很相似,不同的是这里要求和值最大。

假设原始数组是a[1:n],用dp[i]来表示以a[i]结尾的递增子序列的最大和值,显然状态转移方程就是:
dp[i]=a[i]+max{dp[k] | a[k]<=a[i]且1<=k<i}
这样复杂度就是O(n^2)

如果再考虑到当a[i]<a[j]时,所有dp[i]>=dp[j]的情况都不需要保留j状态(也就是说,在我们予以记录的状态中,随着dp值的增加,最后一个元素的值也是单调递增的),算法可以进一步优化到O(n*logn)
FancyMouse 2009-01-19
  • 打赏
  • 举报
回复
lis的结构+改一下dp状态,平方
for(int i=0;i<n;i++)
{
dp[i] = a[i];
for(int j=0;j<i;j++)
if(a[i] > a[j])
dp[i] = max(dp[i], dp[j]+a[i]);
}
绿色夹克衫 2009-01-19
  • 打赏
  • 举报
回复
恩,确实可以优化到nlogn,定义一个结构maxseq

maxseq
{
int sum;
int lastitem;
}

来记录最大递增序列的加和,其中sum为递增序列的和,lastitem为序列中最后一个元素的值,

将这个序列MSeq按照lastitem排序(初始值就是第一个元素),其实这个序列对于sum,也应当是递增的,

如果sum并非递增,则逆序的sum都可以被删除,逆序的肯定不是最优解

以后每读入一个数,就在序列中用二分找到lastitem所处的位置,即MSeq[i].lastitem < a[k] && MSeq[i + 1].lastitem > a[k]

然后计算sum,MSeq[i].sum + a[k],如果sum < MSeq[i + 1].sum,说明当前元素逆序,不做操作,否则删除后面sum逆序的部分,

这样的话每加入一个数,需用二分做查找,效率为nlogM,M为序列的长度,不超过n,另外,每插入1个元素logM,总合不超过nlogM,

每删除一个元素LogM,只有进入队列的才有可能被删除,总合不超过nlogM

所以效率为O(nlogn)

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧