挺好的一道思维题。
分析
因为是对区间修改,多次修改肯定会超时,很容易想到差分。
那么原题的对区间修改就可以转换为下面三个操作(均在差分数组中):
1. 任选一个数+1
2. 任选一个数-1
3. 任选两个数+1和-1
进一步考虑题目的问题,让原数组一样,那么就是
a[1]的值任意,a[2]开始后面的值均为0。
再分析现有的三个操作,最多的操作数肯定是总正数之和或者总负数之和(取大的那个)
显而易见的,因为只能选一个数进行操作。
那么我们再考虑满足当前最少操作数的时候,能出现不同序列的数量,即a[1]的取值能有多少。
如果正数比负数多,那么正数执行操作3减少到0,额外的还能执行加法(加到a[1]身上),也可以不加(即选操作2)。那么不同的数量就是正数比负数多的部分再+1(可以一个都不加)。
反之负数也是如此,但是需要注意负数执行加,那么a[1]就是减,不能小于0。
正负一样多,那肯定就只有一种序列了,因为要求操作数最少。
AC代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;const int N=1e5+5;
int n,a[N],pos,neg;void solve(){cin>>n;for(int i=1,t;i<=n;++i){cin>>t;a[i]+=t;a[i+1]-=t;}for(int i=2;i<=n;++i)if(a[i]<0)neg+=-a[i];else pos+=a[i];cout<<max(pos,neg)<<endl;//最少操作次数if(pos>neg){//正数多cout<<pos-neg+1<<endl;}else if(pos==neg){cout<<1<<endl;}else if(pos<neg){//负数多if(neg-pos<=a[1])cout<<neg-pos+1<<endl;else cout<<a[1]+1<<endl;}
}signed main(){ios::sync_with_stdio(false),cin.tie(nullptr);int t=1;while(t--)solve();return 0;
}