BZOJ3043&&洛谷[Poetize6] IncDec Sequence

版权声明:我这么弱的蒟蒻,虽然博文不是很好,但也请标明转发地址喵! https://blog.csdn.net/ACerAndAKer/article/details/82769106

日常毒瘤

不难发现,我们对序列两两做差,得到一个差分数组,有三种情况d[i]=0,i 和i-1相等,d[i]>0,i大于i-1,d[i]<0,i小于i-1,对于第一种情况,显然要更改的话就是一起改,对于第二种情况和第三种情况 ,每次修改一段区间,这一段的d都不会变,所以就相当于在d的一个位置+1,在另一个位置-1,另一个显然的性质就是最后序列一样时,d等于0,然后我们统计一下 s 1 = i = 1 n d [ i ] &gt; 0 s1=\sum_{i=1}^nd[i]&gt;0 ,还有 s 2 = a b s ( i = 1 n d [ 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; 
}

猜你喜欢

转载自blog.csdn.net/ACerAndAKer/article/details/82769106