欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

洛谷 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

相关标签: 其他