糖果传递

原题链接

思路分析:环形均分纸牌模型
设总和为 s u m s sums sums,共有 n n n张牌,易得 a v g = s u m s n avg=\frac{sums}{n} avg=nsums。由下图我们可以列出关系式: { a 1 + x 2 − x 1 = a v g a 2 + x 3 − x 2 = a v g … a n + x 1 − x n = a v g \begin{cases} a_1+x_2-x_1=avg& \\ a_2+x_3-x_2=avg& \\ \ldots \\ a_n+x_1-x_n=avg \end{cases} a1+x2x1=avga2+x3x2=avgan+x1xn=avg
便有 a n s m i n = ∣ x 1 ∣ + … + ∣ x n ∣ ans_{min}=|x_1|+\ldots+|x_n| ansmin=x1++xn
合并同类型,整理易得:
{ x 2 − x 1 = a v g − a 1 x 3 − x 2 = a v g − a 2 … x 1 − x n = a v g − a n \begin{cases} x_2-x_1=avg-a_1& \\ x_3-x_2=avg-a_2& \\ \ldots \\ x_1-x_n=avg-a_n \end{cases} x2x1=avga1x3x2=avga2x1xn=avgan
由于 x 1 − x n = a v g − a n x_1-x_n=avg-a_n x1xn=avgan,推导得 x n = x 1 − ( a v g − a n ) x_n=x_1-(avg-an) xn=x1(avgan)。同理,易得 x n − 1 = x n − ( a v g − a n − 1 ) x_{n-1}=x_n-(avg-a_{n-1}) xn1=xn(avgan1)。代入 x n x_n xn后不难发现所有的 x i x_i xi均可以由 x 1 x_1 x1推导得到,所以就有 x i = x 1 − C i x_i=x_1-C_i xi=x1Ci C i = C i + 1 + a v g − a i ( i > = 1 ) C_i =C_{i+1}+avg-a_i (i>=1) Ci=Ci+1+avgai(i>=1)。其中 C 1 = 0 C_1=0 C1=0,那么 a n s m i n ans_{min} ansmin就等价于 ∣ x 1 − C 1 ∣ + ∣ x 1 − C 2 ∣ + … + ∣ x 1 − C n ∣ |x_1-C_1|+|x_1-C_2|+\ldots+|x_1-C_n| x1C1+x1C2++x1Cn。原问题就转化为在数轴上取一点 x 1 x_1 x1
使得该点到 C i C_i Ci的距离总和最小。
糖果传递_第1张图片

C o d e : Code: Code:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include 
using namespace std;
#define MaxN 1000010
//#define MOD 998244353
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define endl '\n'
#define LL long long
#define PII pair
#define rint register int 
#define ULL unsigned long long
const int MOD=1e9+7;
//int days[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
//int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
template<class T> inline void read(T& x){
    x=0;int f=0;char ch=getchar();
    while( !isdigit(ch) ) f|=( ch == '-' ) , ch=getchar();
    while( isdigit(ch) )  x = ( x<<1 ) + ( x<<3 ) + ( ch^48 ) , ch=getchar();
    x = f ? -x : x;
}
template<class T> inline void print(T x){
    if ( x < 0 ) { putchar('-'); x = -x; }
    if ( x >= 10 ) print( x / 10 );
    putchar(x % 10 + '0');
}
LL A[MaxN],C[MaxN];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n;
    cin>>n;
    LL sums=0,avg;
    for(int i=1; i<=n; i++){
        cin>>A[i];
        sums+=A[i];
    }
    avg=sums/n;
    for(int i=n; i>=1; i--){
        C[i]=C[i+1]+avg-A[i];
    }
    C[1]=0;
    sort(C+1,C+1+n);
    LL ans=0;
    for(int i=1; i<=n; i++) ans+=abs(C[i]-C[(n+1)/2]);
    cout<<ans;
    return 0; 
} 

你可能感兴趣的:(题解)