P1121 环状最大两段子段和

题目描述

给出一段环状序列,即认为\(A_1\)和\(A_N\)是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大。

输入输出格式

输入格式:

第一行是一个正整数\(N(N≤2×10^5)\) ,表示了序列的长度。

第二行包含\(N\)个绝对值不大于10000的整数\(A_i\),描述了这段序列,第一个数和第\(N\)个数是相邻的。

输出格式:

一个整数,为最大的两段子段和是多少。


最开始想的倍增优化,感觉其实好像也可以做,但写起来复杂到毁天灭地。

于是听教练讲了\(O(n)\)的做法。

先考虑单链情况。

对于这个序列,我们首先划分它的状态

其中\(S1\)区和\(S3\)区是选中的两段。

不妨就把这些划分为\(dp\)的状态。

令\(dp[i][j]\)代表在长度\(i\)时处于\(j\)区的最大答案

状态转移:

\(dp[i][0]=max(dp[i-1][0],dp[i-1][3]);\)

\(dp[i][1]=max(dp[i-1][4],dp[i-1][1])+a[i];\)

\(dp[i][2]=max(dp[i-1][1],dp[i-1][2]);\)

\(dp[i][3]=max(max(dp[i-1][2],dp[i-1][1]),dp[i-1][3])+a[i];\)

\(dp[i][4]=dp[i-1][4];\)

容易发现,\(dp[i][4]\)总是0,遂可以扔掉这一维。

解决了单链的,我们想一想如果推广到环上。一般的方法是延长链为两倍,但这个并不是区间\(dp\),所以很难限定区间。

这里提供一种类似于费用提前的做法。

还是这张图,假设选取了\(s0,s2,s4\)三段



不就是把环连起来了吗

于是问题就转化到了找最小两段子段和上,做法是一样的。

不过需要注意的是,最小子段和不能两端同时取到端点,否则就是单段最大子段和了。


code:

#include <cstdio>
#include <cstring>
int min(int x,int y) {return x<y?x:y;}
int max(int x,int y) {return x>y?x:y;}
const int N=200010;
const int inf=0x3f3f3f3f;
int a[N],dp[N][4],n,ans=-inf,sum=0;//0不选右,1左段,2中间不选,3右段
void dp1()
{
memset(dp,-0x3f,sizeof(dp));
dp[1][1]=a[1];
for(int i=2;i<=n;i++)
{
dp[i][0]=max(dp[i-1][0],dp[i-1][3]);
dp[i][1]=max(0,dp[i-1][1])+a[i];
dp[i][2]=max(dp[i-1][1],dp[i-1][2]);
dp[i][3]=max(max(dp[i-1][2],dp[i-1][1]),dp[i-1][3])+a[i];
}
ans=max(dp[n][0],dp[n][3]);
}
void dp2()
{
memset(dp,0x3f,sizeof(dp));
dp[1][1]=a[1];
for(int i=2;i<=n;i++)
{
dp[i][0]=min(dp[i-1][0],dp[i-1][3]);
dp[i][1]=min(0,dp[i-1][1])+a[i];
dp[i][2]=min(dp[i-1][1],dp[i-1][2]);
dp[i][3]=min(min(dp[i-1][1],dp[i-1][2]),dp[i-1][3])+a[i];
}
ans=max(ans,sum-dp[n][0]);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
sum+=a[i];
}
dp1();
dp2();
printf("%d\n",ans);
return 0;
}

2018.6.6

洛谷 P1121 环状最大两段子段和 解题报告的更多相关文章

  1. 洛谷P1121 环状最大两段子段和

    题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的第一行是一个正整数N,表示了序列 ...

  2. 洛谷 P1121 环状最大两段子段和

    https://www.luogu.org/problemnew/show/P1121 不会做啊... 看题解讲的: 答案的两段可能有两种情况:一是同时包含第1和第n个,2是不同时包含第1和第n个 对 ...

  3. 洛谷 P1121 环状最大两段子段和 题解

    每日一题 day57 打卡 Analysis 对于这个问题,由于分成了两个子序列,我们不妨就是枚举一下可能出现的情况: 无非就这两种: 1.+++++0000+++++0000++++ 2.0000+ ...

  4. P1121 环状最大两段子段和

    P1121 环状最大两段子段和 题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的 ...

  5. P1121 环状最大两段子段和(DP)

    P1121 环状最大两段子段和 难度 提高+/省选- 题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件 ...

  6. luogu P1121 环状最大两段子段和

    嘟嘟嘟 一道说难也难说简单也简单的dp题. 我觉得我的(有篇题解)做法就属于特别简单的. 平时遇到环的问题都是断环为链,但这道题给了一种新的思路. 观察一下,最后的答案无非就这两种:xxx--xx-- ...

  7. 【u124】环状最大两段子段和

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. ...

  8. luogu 1121 环状最大两段子段和

    题目大意: 一个序列看做一个环 选两段数使它们和最大 思路: 定义一个dp数组i j 0/1 表示前i个取了连续的j段 0/1表示取不取第i个 但是因为看做一个环 首尾相接的情况可以看做是选三段,其中 ...

  9. 洛谷 P1291 [SHOI2002]百事世界杯之旅 解题报告

    P1291 [SHOI2002]百事世界杯之旅 题目描述 "--在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字.只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽 ...

随机推荐

  1. Opencv 2.4.10 +VS2010 项目配置

    资料来源:http://blog.csdn.net/scottly1/article/details/40978625

  2. java使用何种类型表示精确的小数?

    问题 java使用何种类型表示精确的小数? 结论 float和double类型的主要设计目标是为了科学计算和工程计算,速度快,存在精度丢失 BigDecimal用来表示任意精确浮点数运算的类,在商业应 ...

  3. Awesome Python,Python的框架集合

    Awesome Python A curated list of awesome Python frameworks, libraries and software. Inspired by awes ...

  4. 自从硬派网倒闭后,就没有什么好看的IT硬件网站了

    RT

  5. Oracle数据库设置为归档模式的操作方法

    Oracle归档模式非常非常重要!对于有些数据库刚装好后可能是非归档模式,这是很危险的!为了安全起见,一定要谨记:对于Oracle数据库,一定要设置为归档模式,尤其是生产库,只有这样才能实现数据库的有 ...

  6. Git分支管理的策略梳理

    当下最流行的版本管理系统应该是非Git莫属.相比同类软件,Git有很多优点,其中很显著的一点,就是版本的分支(branch)和合并(merge)十分方便.有些传统的版本管理软件,分支操作实际上会生成一 ...

  7. B. Vasya and Isolated Vertices

    链接 [http://codeforces.com/contest/1065/problem/B] 题意 给你n个点,m条边,让你找最多孤立点和最少孤立点,不能有自环路 分析 对于最少max(0,n- ...

  8. Mooc总结——Linux内核分析

    朱荟潼+ 原创作品转载请注明出处 :<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 学习笔记链接汇总 第 ...

  9. Beta版发布说明

    我们的作品“校友聊”软件的最终版本于6月19日最终发布了,下面我们将对自己的产品进行介绍. 在使用之前,首先要进行用户注册,用户可以自行设置自己的账号,姓名,密码,签名,头像等信息,头像信息也可以在文 ...

  10. s标签s:if和s:set实现一个表格显示为多个表格

    1.首先本来这个表格是这样的 2.这时候代码是这样的 <table cellpadding="4"> <tr> <th>指标点</th&g ...