[HAOI2008]糖果传递

link

很巧妙的一道贪心。

首先有一个思路就是整个过程的最终效果等于每个点有一个值x,代表这个点向右(或者向左)传递的糖果数量,那么就会发现需要满足 \(A_i+X_{i-1}+X_i=ave\) ,然后把一个通项式列出来发现所有的x都可用x1,A和V来表示,于是问题就变成了求数轴上一点到所有点距离之和最小值的简单贪心。

代码五分钟推式两小时,良心。

code:

#include<bits/stdc++.h>
//#define zczc
#define int long long
const int N=1000010;
using namespace std;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline int max(int s1,int s2){
	return s1<s2?s2:s1;
}
inline int aabs(int s1){
	return s1<0?-s1:s1;
}

int m,a[N],s[N];

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);int v=0;
	for(int i=1;i<=m;i++){
		read(a[i]);v+=a[i];
	}
	v/=m;
	for(int i=1;i<=m;i++)a[i]=a[i-1]+v-a[i];
	sort(a+1,a+m+1);
	int ss=a[m/2],ans=0;
	for(int i=1;i<=m;i++)ans+=aabs(a[i]-ss);
	printf("%lld",ans);
	
	return 0;
}
posted @ 2022-06-27 21:03  Feyn618  阅读(24)  评论(0编辑  收藏  举报