#4886. 数列分段
数列分段
Background
数列分段(segment)
【题目描述】
给你一个长度为n(1≤n≤10^6^)的整数数列a~1~, a~2~, …, an(−10^9^≤ai≤10^9^)。你需要将这个数列分成若干段连续子序列,使得这些连续子序列的价值之和最大。
我们定义一个连续子序列的价值为:这个子序列中最大的数与最小的数之差。
【输入格式】
第一行包含一个整数n,表示数列的长度(1≤n≤10^6^)。
第二行包含n个整数,其中第i个整数表示数列中的第i个元素ai(−10^9^≤ai≤10^9^),相邻两数之间以一个空格分隔。
【输出格式】
一个整数,表示所有划分方案中,子序列价值之和的最大值。
【样例1输入】
【样例1输出】
【样例1解释】
一种最优划分方案是将该序列划分为2个子序列 [1 2 3] [1 2],对应的子序列价值和为 (3−1)+(2−1)=3。
【样例2输入】
【样例2输出】
【样例2解释】
因为原序列中每个元素均为3,所以无论如何划分,每个子序列的价值均为0,对应的价值和也为0。
【样例3】
见选手目录下的segment/segment3.in与segment/segment3.ans(见CCF官方网站)。
【数据范围与提示】
对于20% 的数据,n≤100。
对于40% 的数据,n≤1000。
对于60% 的数据,n≤10000。
对于100% 的数据,1≤n≤10^6^,−10^9^≤ai≤10^9^。
提示
设 val(l,r) 表示从a~l~到ar 这段连续子序列对应的价值。
首先,若数列本身是单调递增(a~1~≤a~2~≤…≤an)或单调递减(a~1~≥a~2~≥…≥an)的,则不需要对其进行划分,其对应的价值之和为val(1,n)=|a~1~−an|,其中任意两对相邻元素ai和ai~+1~恰好贡献了 |ai−ai~+1~| 的价值,价值和可以表示为 |a~1~−a~2~|+|a~2~−a~3~|+…+|an−~1~−an|。此时,如果在ai和ai~+1~之间进行了划分,则将会损失 |ai−ai~+1~| 的价值。因此,对于本身就单调递增或者单调递减的数列,不需要进行划分就能够得到最大价值。
其次,我们分析数列中只存在一个极值(假设为ak)的情况,此时可能有如下两种不同的情况。
(1)a~1~≤a~2~≤…≤ak≥ak~+1~≥…≥an。
(2)a~1~≥a~2~≥…≥ak≤ak~+1~≤…≤an。
针对第一种情况(ak是极大值),我们可以得出如下结论。
(1)若不对这个数列进行划分,其对应的价值和为val(1,n)=max{|a~1~−ak|, |ak−a~n~|}。
(2)若在ak−~1~和ak之间进行划分,其对应的价值和为val(1,k−1)+val(k,n)=|a~1~−ak−~1~|+|ak−an|≥val(1,n),而当i<k时,在ai−~1~和ai之间进行划分的价值和为val(1, i−1)+val(i, n)=|a~1~−ai−~1~|+|ak−an|≤val(1, k−1)+val(k, n)。
(3)若在ak和ak~+1~之间进行划分,其对应的价值和为val(1,k)+val(k+1,n)=|a~1~−ak|+|ak~+1~−an|≥val(1,n),而当i>k时,在ai−~1~和ai之间进行划分的价值和为val(1, i−1)+val(i, n)=|a~1~- ak|+|ai−an|≤val(1,k)+val(k+1, n)。
因此此时的最优方案是选择在ak−~1~和ak之间进行一次划分,或者在ak和ak~+1~之间进行一次划分。
第二种情况(ak是极小值)的最优划分方案同第一种情况。
由更一般的分析可得,使价值和最大的划分方案中必然存在一种方案,使得划分出来的每一个连续子序列都是单调递增或者单调递减的。此时我们需要考虑的是,对于序列中存在的若干个极值(假设为ak),我们是在其与ak−~1~之间进行一次划分,还是在其与ak~+1~之间进行一次划分。
针对这个问题,我们可以使用动态规划算法求解,定义状态f~i~ 表示a~1~到a~i~ 这段连续子序列能够得到的最大价值和。
(1)若ai−~2~≤ai−~1~≤ai或ai−~2~≥ai−~1~≥ai,说明ai−~1~必然不是极值点,此时ai−~2~和ai−~1~之间及ai−~1~和ai之间都不会有划分,前i个数能够获得的最大价值和等于前i−1个数能够获得的最大价值和加上ai−~1~和ai 这一对数单独贡献的价值 |ai−~1~−ai|,即fi=fi−~1~+|ai−~1~−ai|;否则,说明ai−~1~是一个极值,此时需要在ai−~2~和ai−~1~之间或者在ai−~1~和ai之间进行一次划分。
(2)若在ai−~2~和ai−~1~之间进行一次划分,则fi=fi−~2~+|ai−~1~−ai|。
(3)若在ai−~1~和ai之间进行一次划分,则fi=fi−~1~。
即fi=max{ fi−~2~+|ai−~1~−ai|, fi−~1~},最大价值和为fn。
Limitation
1s, 1024KiB for each test case.