题目描述
给定一个长度为 nn 的数列 {a_1,a_2,\cdots,a_n}a1,a2,⋯,an,每次可以选择一个区间[l,r][l,r],使这个区间内的数都加 11 或者都减 11。
请问至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列有多少种。
输入格式
第一行一个正整数 nn
接下来 nn 行,每行一个整数,第 i+1i+1行的整数表示 a_iai。
输出格式
第一行输出最少操作次数
第二行输出最终能得到多少种结果
输入输出样例
输入 #1复制
4 1 1 2 2
输出 #1复制
1 2
说明/提示
对于 100\%100% 的数据,n\le 100000, 0 \le a_i \le 2^{31}n≤100000,0≤ai≤231。
差分介绍: s[i]=a[i]-a[i-1] (s差分数组,a原数组)
定义:
1.差分数组的前缀和就是原数组。sum[i]=a[i]=s[i]+sum[i-1];
前缀和数组的差分就是原数组。
2. 【l,r】区间都加上x 只需改变 s[l]:+x s[r+1]:-x
思路:
1.要使所有:数相同-->其数组的从2到n的差分数组都为0.
如最后全为 1 1 1 1
b[1]=1 ,b[2]=1-1=0, b[3]=1-1=0....
2.得到的差分数组的值为正数或负数(0不需要花费代价了)那么将正数-1同时负数+1作为一步时,代价是最小的。
如 [l,r]+1 ---->b[l]+1 ,b[r+1]-1 此时b[l]<0, b[r+1]>0
[l,r] -1 ----->b[l]-1 b[r+1]+1 此时b[l]>0 b[r+1]<0
所以 差分的正负顺序没关系的。
设zh为2-n差分数组的正数之和,fh为负差分的绝对值之和。
则正负相抵消需要 min(zh,fh)步
3. 正负抵消完,还有以下两种情况
(1)全是负数
(2)全是正数
这两种情况都是这个数一步一步加或者一步一步减,需要代价为abs(zh-fh)
综合2,3得到总代价为min(zh,fh)+abs(zh-fh)=max(zh,fh),第一个问题完成。
4.第二问,在已经把2-n的差分数组全为0了,还有b[1]没有考虑。
b[1]也有以下两种情况
(1)b[1]独善其身,跟2-n的没关系,还是原来的b[1],一种方案。
(2)b[1]在2-n正负抵消完后,跟剩下的全是正数、或者全是负数进行配对。
若b[i](还剩下的数)<0,那么b[i]+1,b[1]-1
若b[i]>0,那么b[i]-1,b[1]+1
有abs(zh-fh)种方案
综合上述,一共有abs(zh-fh)+1种方案。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[100005],b[100005];
ll zh,fh;
int main()
{
int n;
cin>>n;
for(int i=1; i<=n; i++){
cin>>a[i];
}
b[1]=a[1];
for(int i=2; i<=n; i++){
b[i]=a[i]-a[i-1];
if(b[i]>0) zh+=b[i];//zh 正差分绝对值之和
else fh+=-b[i];//fh 负差分绝对值之和
}
cout<<max(zh,fh)<<endl<<abs(zh-fh)+1<<endl;
return 0;
}