题意很简单,给一个函数,如果x y差的绝对值小于等于1,函数值为0,否则函数值为y-x
然后给一个数列,求 ∑ f ( a i , a j ) \sum f(a_i,a_j) f(ai,aj) 其中 i &lt; j i&lt;j i<j
首先暴力是不可能暴力的,n那么大,数列考虑一下前缀和,比如现在如果我们不考虑函数值为0的情况,也就是要求 ∑ a j − a i \sum a_j-a_i ajai,那就简单了,记录前缀和,枚举每个数,然后累加 a i ∗ ( i − 1 ) − p r e [ i − 1 ] a_i*(i-1)-pre[i-1] ai(i1)pre[i1],而这题还有0的情况,那我们只要记录j前面有几个数的情况会满足 f ( i , j ) = = 0 f(i,j)==0 f(i,j)==0,怎么记录这个呢,用一个map边计算边扫一遍来记录每个数出现的次数即可,然后对于a[i]来说,a[i]+1和a[i]-1的函数值就是0,也就是刚才上面那个多/少算了1,看这个map对应这个数在前面出现了多少次即可
然后有一个坑点就是会爆long long,要用long double

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=200050;
typedef long long ll;
typedef long double ld;
int n;
ll a[N],sum[N];
map<int,int> cnt;
int main(void){
   
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
   
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    ld ans=0;
    for(int i=1;i<=n;i++){
   
        //printf("%d\n",i);
        ans+=(ld)a[i]*(i-1)-sum[i-1];
        //printf("** %lld\n",a[i]*(i-1)-sum[i-1]);
        ans-=cnt[a[i]-1];
        ans+=cnt[a[i]+1];
        cnt[a[i]]++;
        //printf("--%lld--\n",ans);
    }
    printf("%.0Lf\n",ans);
    return 0;
}