核心思想就是将相同的加法变为求一次乘法
假设arr[i]=7,arr[i+1]=10,则意味着f(7)~f(9)都为i,即f(x)的值是arr数组中相邻的两个左右元素的左元素的下标,其中x属于左右元素形成的左闭右开的区间;
而g函数也是一个个长度为r的小区间中的值是相同的,假如r为5,则意味着g(0)~g(4)都为0;
枚举arr相邻左右元素的时候,讨论左右元素形成的左闭右开的区间与g的小区间重合情况,将相同的加法化为乘法即可。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int arr[100005];
int main()
{
int n,N;
cin >> n >> N;
arr[0]=0;
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
}
arr[n+1]=N;//统一处理
int r=N/(n+1);
int g=0;
long long ans=0;
for(int i=0;i<=n;i++){
int L=arr[i],R=arr[i+1];
int ban=(g+1)*r-1;
if(ban>=R-1){
ans+=(R-L)*(abs(i-g));
}else if(ban>=L && ban<R-1){
ans+=(ban-L+1)*abs(i-g);
g++;
ban=(g+1)*r-1;
while(ban<R-1){
ans+=r*abs(i-g);
g++;
ban=(g+1)*r-1;
}
ans+=(R-1-(ban-r+1)+1)*abs(i-g);
}else if(ban<L){
g++;
i--;
}
}
cout << ans;
return 0;
}