/*
【*差分*】【洛谷P4552】
https://www.luogu.com.cn/problem/P4552
题意:给出一个长度为n的数组 每次可以选择一个区间 对它进行+1 -1操作
求出需要至少多少次操作 可以使数组中的数都一样
并求出 在最少次操作下 最终得到的数列有多少种
分析:差分的思想 cha[1]=nums[1] cha[n]=nums[n]-nums[n-1] n>=2
对于一个差分后的数组 进行区间操作 +x -x
只需要进行 cha[l,r]+x cha[l]+x cha[r+1]-x 最后进行一下前缀和就可以了
这样问题就转换成:求一个差分数组全部为 0 时的最少操作数
差分数组的特性:每一位都是独立的,影响着这个区间的值 只有对它们的每一位进行操作 置为0 最后的前缀和才能为0
当前这个位置l -1 +1 表示 原数组的后面的每一位都+1 -1
而 r+1 +1 -1 表示 操作r+1终止位置 相当于对[l,r]进行了+1 -1的操作
而若r+1>n 超界 那么 操作的区间就是 [l,n]
需要对每一位进行这样的操作 直到最后都为0
所以(结论):
若差分数组中 只有正数或负数 那么最少操作数 就是它们之和 sum(正) sum(负)
若有正有负 便可以同时操作两个 +1 -1可以抵消
分别记录 正数的之和 和 负数之和 抵消后 即为min(sum(正),sum(负)) + abs(sum(正)-sum(负)) = max(sum(正),sum(负))
结果即为--> max(sum(正),sum(负))
而最后操作后的结果的值为 : b[1] b[1] 全都是b[1]的值
那么求有多少种 只需要求 最后的 abs(sum(正)-sum(负)) 有多少次独立的+1 -1 就有多少种 +1(原来的也算一种)
ok 结束 应该了解了差分的真正的用处
*/
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
int a[maxn],cha[maxn];
int main()
{
int n;cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
int p=0,q=0;
for(int i=2;i<=n;i++)
{
cha[i]=a[i]-a[i-1];
if(cha[i]>0)
p+=cha[i];
else
q+=cha[i];
}
cout<<max(p,q)<<"\n"<<abs(p-q)+1;
return 0;
}
【*差分*】【洛谷P4552】
最新推荐文章于 2024-01-23 13:10:46 发布