P2512 [HAOI2008]糖果传递
Sol:
环形均分纸牌问题
- 考虑最基本的均分纸牌问题,相当于将环从1与n之间断开。
令\(res_i\)表示第\(i\)个人达到平均值所用步数,ave$表示糖果的平均数。
则
\(res_1=a_1-ave\)
\(res_2=a_2-ave+res_1=a_1+a_2+2*ave\)
\(res_3=a_3-ave+res_2=a_1+a_2+a_3-3*ave\)
\(\dots\)
\(res_i=a_i-ave+res_{i-1}=\sum_{j=1}^i-i*ave=\sum_{j=1}^i \left(a_j-ave\right)\)
令\(s_i=a_i-ave\),则\(res_i=\sum_{j=1}^is_j\)
所以每个人达到平均值所用步数分别为为\(res_1,res_2,res_3,\dots,res_n\),由于第\(n\)个人不可能再将糖果转移或获得了,因此\(res_n=0\)
所以\(ans=\sum_{i=1}^nres_i\)
- 考虑环形纸牌问题,相当于从环中某点\(k\)断开求一边基本均分纸牌问题
每个人达到平均值所用步数分别为\(res_{k+1}-res_k,res_{k+2}-res_k,\dots,res_{n}-res_k,res_1+res_n-res_k,\dots,res_k+res_n-res_k\)
由于\(res_n=0\)所以\(ans=\sum_{i=1}^n\left| res_i-res_k\right|\)
我们的最终目标是使\(ans\)最小化。
绝对值相当于数轴上数的距离,相当于我们找一个点\(k\),使得它到数轴上其他点的距离之和最小,这是经典的中位数问题,中位数到数轴上其他点的距离之和最小,因此我们选\(res_i\)的中位数即可。当\(n\)为奇数时,选\(res_{\frac{k}{2}+1}\),当\(n\)为偶数时选\(res_{\frac{k}{2}}\)或\(res_{\frac{k}{2}+1}\)都可以。
AC CODE:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read(){
int x=0,f=1;char ch=‘ ‘;
while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘) f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+(ch^‘0‘);ch=getchar();}
return x*f;
}
const int N = 1000000 + 10;
typedef long long ll;
int a[N];
ll s,sum[N];
int main(){
// freopen("data.in","r",stdin);
// freopen("sol.out","w",stdout);
int n;n=read();
int ave;
for(int i=1;i<=n;i++) {
a[i]=read();s+=a[i];
}
ave=s/n;
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]-ave;
sort(sum+1,sum+n+1);
int mid=sum[n/2+1];
long long ans=0;
for(int i=1;i<=n;i++){
ans+=abs(sum[i]-mid);
}
printf("%lld",ans);
return 0;
}
原文地址:https://www.cnblogs.com/Loi-Brilliant/p/9785046.html