洛谷 P4552 [Poetize6] IncDec Sequence (差分)
程序员文章站
2022-07-12 17:40:01
...
题目链接
题目思路
显然在一个区间内做加法和减法要使用差分,然而我没想到。。。
肯定是要使得差分数组[2,n]全部为0,而dif[1]有多少个取值,则决定了有多少个可能取值。
很明显的,在我们求出的差分数组中,有正数也有负数,要消除这些数,使得它们全部归零,我们有以下3种可行的操作:
1:选取一个正数(X)和一个负数(Y),使正数减1,负数加1,这样经过N次操作,我们一定可以以最少的代价将绝对值较小的一方归零,代价为abs(min(X,Y))
2:选取一个正数(X),使其与 S[1] 配对或s[n+1],这样,我们经过N次操作,一定可以将它归零,代价为:abs(X)
3:选取一个负数(Y),使其与 S[n+1] 配对或s[n+1],这样,我们经过N次操作,一定可以将它归零,代价为:abs(Y)
经过上述分析,我们就能够推导出本题的解题公式:
ans=abs(min(X,Y))+abs(X-Y)=abs(max(X,Y))
需要注意的是这里的X,Y是差分数组中所有正数的和与所有负数的和的绝对值
最后我们还要求能构成几组解,这很容易可以推出:
剩下的abs(X-Y)次操作可以配对给d[n+1]或者d[1]所以有abs(x-y)+1种答案
代码
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll n,a[maxn],dif[maxn],zhen,fu;
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(int i=2;i<=n;i++){
dif[i]=a[i]-a[i-1];
if(dif[i]>0){
zhen+=dif[i];
}else{
fu-=dif[i];
}
}
printf("%lld\n%lld\n",max(zhen,fu),abs(zhen-fu)+1);
return 0;
}
参考链接:https://www.luogu.com.cn/blog/TheShadow/p4552-poetize6-incdec-sequence-you-qu-di-ci-fen-ti-xie
上一篇: [POJ3263]Tallest Cow