题意:有操作为选择[i,j]区域,使得区域内的数+1或者-1,求:1.至少需要多少操作使得数列中的数都一样。2.保证最少次数前提下最终可得数列可能有多少组。
设b数组为数列a的差分,b[1] = a[1],b[2] = a[2] - a[1],…,b[n] = a[n]-a[n-1]。再设b[n+1] = 0;
解析题意:利用差分的思想,在[i,j]中同时全部+1可以转化为b[i]+1且b[j+1]-1。
所以转化题意为:在b数列中,每次可以选出b[1]…b[n+1]中的任意两个数,一个+1,一个-1,最终使得b[2]…b[n]的数都为零,最终的a数列就是n个b[1]构成的。
但是要考虑几种情况
- b[2]…b[n]中有正负数同在的时候,每次选择b[2]…b[n]中的数+1,-1
- 选b[1]和b[n]
- 选b[2]…b[n]和b[n+1]
- ~~选b[1]和b[n+1]~~对b[2]…b[n]中无变化
分析:假如有q个正数,p个负数,则1执行了min(p,q)次,接下来还要执行2或3,每个两个都是每次执行一次,所以总共最少次数是min(p,q)+|p-q|=max(p,q)。当把正负抵消了之后,每一次操作都可以执行2操作,在加上本身自己的一个,所以总共有|p-q|+1组。
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int main()
{
const int N = 10005;
int n,a[N],b[N];
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(i==1) b[i] = a[i];
else b[i] = a[i]-a[i-1];
}
int pos=0,neg=0;
for(int i=1;i<=n;i++){
if(b[i]<0) neg++;
if(b[i]>0) pos++;
}
cout<<max(pos,neg)<<endl<<abs(pos-neg)+1;
return 0;
}