CF1534B Histogram Ugliness 题解

题目传送门

题目大意

给定一个 \(n\) 列的直方图,第 \(i\) 列的高度为 \(a_i\)。定义一个直方图的丑陋度为:该直方图所有裸露在外的竖线长度之和。现在你可以在直方图中选出一列,将这一列的高度减 \(1\) ,现在求操作数+操作后直方图丑陋度的最小值。

题目解析

我们发现,只有将中间凸出来的方格去掉才能减小丑陋值。
我们发现,将中间凸出的方格的高度减去 \(1\) 之后就能将丑陋值减小 \(2\) ,那么我们就只能去掉宽度为 \(1\) 凸出来的方格了,因为只有这样才能减小答案。
删的时候记得记录删的次数,保证删完之后当前列不能小于左右两边的任意一列,最后扫一遍得到丑陋值就可以了。
丑陋值的计算公式(这里设 \(a_0=a_{n+1}=0\) ):

\[s=\sum^{n+1}_{i=1}|a_i-a_{i-1}| \]

#include<cstdio>
#define maxn 400039
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
//#define debug
typedef long long ll;
typedef long long Type;
inline int abs(int x){ return x>0?x:-x; }
inline Type read(){
	Type sum=0;
	int flag=0;
	char c=getchar();
	while((c<'0'||c>'9')&&c!='-') c=getchar();
	if(c=='-') c=getchar(),flag=1;
	while('0'<=c&&c<='9'){
		sum=(sum<<1)+(sum<<3)+(c^48);
		c=getchar();
	}
	if(flag) return -sum;
	return sum;
}
int T;
int n;
ll a[maxn];
ll res,ans,tmp;
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
    T=read();
    while(T--){
    	n=read();
    	for(int i=1;i<=n;i++) a[i]=read();
    	a[0]=a[n+1]=res=ans=0;
		for(int i=1;i<=n;i++)
    	    if(a[i]>a[i-1]&&a[i]>a[i+1]){//这里代表是中间凸出来的
    	    	tmp=max(a[i-1],a[i+1]);
    	    	ans+=a[i]-tmp;
    	    	a[i]=tmp;
			}
		for(int i=1;i<=n+1;i++)
			res+=abs(a[i]-a[i-1]);
		printf("%lld\n",ans+res);
	}
	return 0;
}
posted @ 2021-06-16 15:39  jiangtaizhe001  阅读(75)  评论(0编辑  收藏  举报