P2512 [HAOI2008]糖果传递 - 贪心+中位数【环形均分纸牌问题】

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+2ave\( \)res_3=a_3-ave+res_2=a_1+a_2+a_3-3ave\( \)\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;
}
posted @ 2018-10-14 07:24  dprswdr  阅读(342)  评论(0编辑  收藏  举报