BZOJ3293_分金币_KEY

题目传送门

设x[i]表示i+1向i传的糖果数,x[n]表示1向n传的糖果数,a'=(a[1]+...a[N])/N
  a[1]+x[1]−x[n]=a'
  a[2]+x[2]−x[1]=a'
  a[3]+x[3]−x[2]=a'
  ⋯⋯
  a[n−1]+x[n−1]−x[n−2]=a'
  a[n]+x[n]−x[n−1]=a'

把式子变形:
  x[1]=a'−a[1]+x[n]
  x[2]=a'−a[2]+x[1]=2∗a'−a[2]−a[1]+x[n]
  x[3]=a'−a[3]+x[2]=3∗a'−a[3]−a[2]−a[1]+x[n]
  ⋯⋯
  x[n−1]=a'−a[n−1]+x[n−2]=(n−1)∗a'−∑n−1i=1a[i]+x[n]
  x[n]=n∗a'−∑ni=1a[i]+x[n]=0+x[n]

设s[i]=∑a[i]−i∗a',则:
  ans=∑∣x[i]∣ =∑∣s[i]−x[n] ∣
所以当x[n]为{s[1],s[2],...,s[n]}的中位数时答案最小

code:

/**************************************************************
    Problem: 3293
    User: yekehe
    Language: C++
    Result: Accepted
    Time:104 ms
    Memory:2480 kb
****************************************************************/
 
#include <cstdio>
#include <algorithm>
using namespace std;
 
char tc()
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
 
long long read()
{
    char c;while(c=tc(),(c<'0'||c>'9')&&c!='-');
    long long x=0,y=1;c=='-'?y=-1:x=c-'0';
    while(c=tc(),c>='0'&&c<='9')x=x*10+c-'0';
    return x*y;
}
 
const int MAXN=100005;
 
long long N,a[MAXN],sum[MAXN],w,ans,K;
int i;
int main()
{
//  freopen("x.txt","r",stdin);
    N=read();for(i=1;i<=N;i++)a[i]=read(),w+=a[i];
    w=w/N;for(i=1;i<=N;i++)sum[i]=sum[i-1]+a[i]-w;
    sort(sum+1,sum+N+1);for(K=sum[N+1>>1]+sum[(N>>1)+1]>>1,i=1;i<=N;i++)ans+=abs(K-sum[i]);
    printf("%lld",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Cptraser/p/8253109.html