这是一道经典的差分题。
思路大概是这样的:
对于输入的序列a(假定长度为n)
我们求出他的差分序列sum
那么题目就转化成了用最少的步数使得差分序列sum的2~n项都为0
那么就有以下的几种决策:
- 第i位+1,第j位-1
- 第1位+1,第j位-1
- 第i位+1,第n+1位-1
显然,在sumi和sumj一正一负的前提下,我们应该尽可能多的使用第一种,这样才能使答案最优。
统计sum数组当中正整数的和为p,负整数的和为q,那么能用min(q,p)次决策1。剩下的使用|p-q|次决策2,3。
所以答案为max(q,p),能产生|p-q|+1种情况。
1 #include <iostream> 2 #include <cstdio> 3 typedef long long ll; 4 inline ll read() { 5 ll ret=0,f=1; 6 char c=getchar(); 7 while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();} 8 while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar(); 9 return ret*f; 10 } 11 using namespace std; 12 ll a[100010],sum[100010],n,zheng,fu; 13 ll abs(ll x) { 14 return x>0?x:-x; 15 } 16 int main() { 17 n=read(); 18 for(int i=1;i<=n;i++) { 19 a[i]=read(); 20 sum[i]=a[i]-a[i-1]; 21 } 22 for(int i=2;i<=n;i++) { 23 if(sum[i]>0) zheng+=sum[i]; 24 else fu+=(0-sum[i]); 25 } 26 printf("%lld %lld",max(zheng,fu),abs(zheng-fu)+1); 27 return 0; 28 }