vj题单 P4552 [Poetize6] IncDec Sequence

思路:

一次操作:选一个区间[l, r],把这个区间的数都加1或者都减1,可以将求该数列的差分数组b然后来进行该操作

复制代码
一次操作的两种种情况:(l可以等于r)
1.b[l]+1   b[r+1]-1
2.b[l]-1   b[r+1]+1

Q1:至少多少次操作能使数列所有数都一样?

等价于:至少多少次操作可以使b[i](i != 1)等于0?

方案一:

b[1]+1,b[i]-1

b[1]-1,b[i]+1

执行次数:正数的绝对值加负数的绝对值

方案二:让除了b[1]以外的其他正负数相互抵消,最后只剩b[1]和若干项不为0的b的元素

b[i]+1,b[j]-1

b[i]-1,b[j]+1

执行次数:若正数绝对值>负数绝对值,则执行次数为正数绝对值,反之,则为负数绝对值

对比两个方案,显然,后者是最少执行次数

Q2:在保证最少次数的前提下,最终得到的数列有多少种?

等价于:由方案2,我们可以确定最少次数,在得到最终的常数列前,要经过多少个不同的数列?

复制代码
5 0 1 1 -4
5 0 0 1 -3
5 0 0 0 -2  
上述过程代表方案2的处理过程
最后得到5 0 0 0 -2
在得到5 0 0 0 0 前
我们会经过两个数列:
即b[1]-1,b[5]+1  : 4 0 0 0 -1
 b[1]-1,b[5]+1   : 3 0 0 0 0

容易知道:经过的数列数为max(正数绝对值,负数绝对值)-min(正数绝对值,负数绝对值)

笔者答案:
复制代码
#include<stdio.h>
long long a[100001];
int main ()
{
	long long n;
	long long b[100001];
	scanf("%lld",&n);
	long long i;
	for(i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		b[i]=a[i]-a[i-1];
	}
	long long z=0,f=0,max,Abs;
	for(i=2;i<=n;i++)
	{
		if(b[i]>0)
		{
			z+=b[i];
		}
		else
		{
			f+=(-b[i]);
		}
	}
	if(z>f)
	{
		max=z;
		Abs=z-f;
	}
	else
	{
		max=f;
		Abs=f-z;
	}
	printf("%lld\n%lld",max,Abs+1);
	return 0;
}
相关推荐
数研小生3 小时前
构建命令行单词记忆工具:JSON 词库与艾宾浩斯复习算法的完美结合
算法·json
芒克芒克3 小时前
LeetCode 题解:除自身以外数组的乘积
算法·leetcode
Python 老手4 小时前
Python while 循环 极简核心讲解
java·python·算法
@Aurora.4 小时前
优选算法【专题九:哈希表】
算法·哈希算法·散列表
爱看科技4 小时前
微美全息(NASDAQ:WIMI)研究拜占庭容错联邦学习算法,数据安全与隐私保护的双重保障
算法
彷徨而立4 小时前
【C/C++】什么是 运行时库?运行时库 /MT 和 /MD 的区别?
c语言·c++
qq_417129254 小时前
C++中的桥接模式变体
开发语言·c++·算法
Hello World . .5 小时前
数据结构:队列
c语言·开发语言·数据结构·vim
YuTaoShao5 小时前
【LeetCode 每日一题】3010. 将数组分成最小总代价的子数组 I——(解法二)排序
算法·leetcode·排序算法
Abona5 小时前
C语言嵌入式全栈Demo
linux·c语言·面试