BZOJ2439【中山市选2011】序列

题面

题解

设$f[i]$表示将$[1,i]$修改为递增的最小代价,

$g[i]$表示将$[i,n]$修改为递减的最小代价。

$L[i]$表示将$[1,i]$修改为倒$\text V$的代价

$$ \therefore L[i]=min_{2<j<i}\left\{max(g[i]-g[j],f[j])\right\} $$

$R[i]$同理

$$ \therefore ans=min_{2<i<n-1}\left\{L[i] + R[i]\right\} $$

代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<climits>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define clear(x, y) memset(x, y, sizeof(x))

inline int read()
{
	int data = 0, w = 1; char ch = getchar();
	while(ch != '-' && (!isdigit(ch))) ch = getchar();
	if(ch == '-') w = -1, ch = getchar();
	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
	return data * w;
}

const int maxn(1e5 + 10);
int a[maxn], n, j;
long long f[maxn], g[maxn], L[maxn], R[maxn], ans = LLONG_MAX;

int main()
{
#ifndef ONLINE_JUDGE
	file(cpp);
#endif
	n = read(), a[0] = -1, j = 2;
	for(RG int i = 1; i <= n; i++) a[i] = read();
	for(RG int i = 1; i <= n; i++)
		f[i] = f[i - 1] + std::max(a[i - 1] - a[i] + 1, 0);
	for(RG int i = n; i >= 1; i--)
		g[i] = g[i + 1] + std::max(a[i + 1] - a[i] + 1, 0);
	for(RG int i = 3; i < n - 1; i++)
	{
		while(j < i - 1 && std::max(f[j + 1], g[j + 1] - g[i])
				<= std::max(f[j], g[j] - g[i])) ++j;
		L[i] = std::max(f[j], g[j] - g[i]);
	}
	j = n - 1;
	for(RG int i = n - 2; i > 2; i--)
	{
		while(j > i + 1 && std::max(g[j - 1], f[j - 1] - f[i])
				<= std::max(g[j], f[j] - f[i])) --j;
		R[i] = std::max(g[j], f[j] - f[i]);
	}
	for(RG int i = 3; i < n - 1; i++) ans = std::min(ans, L[i] + R[i]);
	printf("%lld\n", ans);
	return 0;
}
posted @ 2019-01-04 14:36  xgzc  阅读(146)  评论(0编辑  收藏  举报