uva 11300 分金币(利用绝对值加和进行求出最小值)

//qq 767039957 welcome
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long LL; 
typedef unsigned long long ULL;
//这里有点类似于隔离分析法,设 xi为第i个人给上一个人的金比数可正可负 
//Di为第1个人到第i个人的金币数总和,M 为每个人的最终金币数 
//有 
//-x1+xi+Di-1==(i-1)*M  
// xi=(i-1)*M+x1-Di-1

// 重要的就是 Di-1-(i-1)*M 
//依据这个式子 用x1表示所有人的xi 最后绝对值相加求中位数 (既是绝对值和最小值
vector<LL> g;
vector<LL>S;// 保存Di-1 - (i-1)*M 
 
int main(){
//	freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	LL n,t;
	ULL gold_sum=0,M,D,m;
	while(~scanf("%lld",&n)){
		S.clear();
		g.clear();
		gold_sum=0;
		for(int i=0;i<n;i++){
			scanf("%lld",&t);
			g.push_back(t);	
			gold_sum+=t;
		}
		M=gold_sum/n;
		D=0; 
		m=0;
		for(vector<LL>::iterator iter=g.begin();iter!=g.end();iter++){
//			cout<<D-m<<"
";
			S.push_back(D-m);
			D+=*(iter);
			m+=M;			 
		} 
	    nth_element(S.begin(),S.begin()+S.size()/2,S.end());
		LL key=S[S.size()/2];
		ULL ans=0;
		for(vector<LL>::iterator iter=S.begin();iter!=S.end();iter++){
			ans+=abs(key-*(iter));
		}
		printf("%llu
",ans); 
	}	
	return 0;
}
原文地址:https://www.cnblogs.com/sfzyk/p/8532410.html