欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

BZOJ3043&&洛谷[Poetize6] IncDec Sequence

程序员文章站 2022-07-12 17:40:25
...

日常毒瘤

不难发现,我们对序列两两做差,得到一个差分数组,有三种情况d[i]=0,i 和i-1相等,d[i]>0,i大于i-1,d[i]<0,i小于i-1,对于第一种情况,显然要更改的话就是一起改,对于第二种情况和第三种情况 ,每次修改一段区间,这一段的d都不会变,所以就相当于在d的一个位置+1,在另一个位置-1,另一个显然的性质就是最后序列一样时,d等于0,然后我们统计一下s1=i=1nd[i]&gt;0s1=\sum_{i=1}^nd[i]&gt;0,还有s2=abs(i=1nd[i]&lt;0)s2=abs(\sum_{i=1}^nd[i]&lt;0),然后我们最后的结果就是把s1和s2全部消成0,每次只会+1或-1,所以不难发现每次最优操作都会使s1和s2对消,最后还会剩下,所以少就是需要max(s1,s2)次
然后对于第二问,就是相当于第一问的操作把他们先修改成递增/递减(也就是说对消完后,剩下的正负都是一样的),然后每次修改相当于是一个单点修改,也就是说可以直接改到结尾,那么就是一个+1/-1,也可以改到开头也是+1/-1,所以有abs(s1-s2)+1种修改方法

代码

//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lli long long int
using namespace std;
const int M=100500;
lli n,a[M],d[M];
inline lli read()
{
	lli x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}
signed main()
{
	n=read();lli ans=0,que=0;
	for (int i=1;i<=n;i++) a[i]=read();
	for (int i=2;i<=n;i++)
	if (a[i]>a[i-1]) ans+=a[i]-a[i-1];
	else que+=a[i-1]-a[i];
	cout<<max(ans,que)<<endl<<abs(ans-que)+1;
	return 0; 
}