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. Iptables防火墙规则使用梳理

    iptables是组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤.封包重定向和网络地址转换(NAT)等功能 ...

  2. centos6.8下LNMP (nginx1.8.0+php5.6.10+mysql5.6.12) - 部署手册

    在平时运维工作中,经常需要用到LNMP应用框架.以下对LNMP环境部署记录下: 1)前期准备:为了安装顺利,建议先使用yum安装依赖库[root@opd ~]#yum install -y make ...

  3. Python 可调用对象

    除了用户定义的函数,调用运算符(即 ())还可以应用到其他对象上.如果想判断对象能否调用,可以使用内置的 callable() 函数.Python 数据模型文档列出了 7 种可调用对象.(1)用户定义 ...

  4. Pair Project 1 elevator

    结对编程——电梯调度 12061181 高孟烨 12061182 郝倩 1.结对编程的优缺点: 优点:结对编程可以结合两个人各自擅长之地,充分发挥两个人各自的优势,两个人一起合作效率会更高.一份工作两 ...

  5. Android中Json数据读取与创建的方法

    转自:http://www.jb51.net/article/70875.htm 首先介绍下JSON的定义,JSON是JavaScript Object Notation的缩写. 一种轻量级的数据交换 ...

  6. NLP笔记:词向量和语言模型

    NLP问题如果要转化为机器学习问题,第一步是要找一种方法把这些符号数学化. 有两种常见的表示方法: One-hot Representation,这种方法把每个词表示为一个很长的向量.这个向量的维度是 ...

  7. HttpServletResponse类学习

    /*//2) 乱码的解决. //设置服务器输出的编码为UTF-8---在BaseServlet处已经已经进行了设置 response.setCharacterEncoding("UTF-8& ...

  8. octave基本指令4

    octave基本指令4 图形化显示数据 >> t=[0:0.01:0.98]; >> y1 = sin(2*pi*4*t); %pi表示π >> plot(t,y1 ...

  9. OpenCV Code: Operations on Mat element

    cv::Mat img = cv::imread("image.jpg"); Method 1: img.at<uchar>(i, j, k) Method 2: im ...

  10. APS.NET MVC4生成解析二维码简单Demo

    一.视图 @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewpor ...