《Tzoj-3927》dp思路

题意:给你一个环形序列,让你求最大连续子序列和.
解法:环形的最大连续子序列和问题
一开始我的思路是化环为链,然后去dp,但是这样就不能保证有没有重复。
如果要保证没有重复。
那就需要去枚举长度,这样时间复杂度就会升到n^2。
正解思路:
首先这个子序列肯定分为两种情况:
1.跨过了首尾.
2.没有跨过首尾.
对于2我们只需要传统的dp就行了.即普通地求最大连续子序列和
对于1这种情况,我们可以求得最小的连续子序列,这样我们用序列总和减去它,那就是最大的了.
如果求最小的连续子序列:我们可以先将序列的每个数取反,然后就变成了求最大连续子序列。
然后用总的去减去这个和的相反数(其实就是加上这个和)
对于这两种情况我们比较下哪个更大,然后输出.
需要注意的是,当这个序列全是负数时,我们第二种情况会是最小的负数,但是第一种情况我们计算出来会是0.
所以我们需要在输入后判断是不是全是负数,如果全是负数,我们就不考虑第一种情况了.(注意数据会爆longlong)

LL a[N],dp[N];
int main()
{
 int t,n;
 sd(t);
 while(t--)
 {
  LL sum = 0;
  int cnt = 0;
  sd(n);
  for(int i=0;i<=n;++i) dp[i] = 0;
  for(int i=1;i<=n;++i) 
  {
   sld(a[i]),sum += a[i];
   if(a[i] < 0) cnt++;
  }
  LL ans = -INF;
  for(int i=1;i<=n;++i) 
  {
   dp[i] = max(dp[i-1],LL(0))+a[i];
   ans = max(ans,dp[i]);
   a[i] = -a[i];
  }
  if(cnt == n)
  {
   plr(ans);
   continue;
  }
  LL temp = -INF;
  for(int i=0;i<=n;++i) dp[i] = 0;
  for(int i=1;i<=n;++i) dp[i] = max(dp[i-1],LL(0))+a[i],temp = max(temp,dp[i]);
  LL t = sum+temp;
  printf("%lld\n",ans>=t?ans:t);
 }
 system("pause");
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值