[BZOJ1045] [HAOI2008] 糖果传递 [结论]

link

如果不是圈,可以从 1 ∼ n \mathfrak{1\thicksim n} 1n递推
规定一个标准传递方向,可以把顺方向的传递记作正权,反方向记作负权。
每一步把 t e m p \mathfrak{temp} temp(初始化为 0 \mathfrak{0} 0)累加上 a i − a ‾ \mathfrak{a_i-\overline{a}} aia a n s \mathfrak{ans} ans(初始化为 0 \mathfrak{0} 0)累加上 t e m p \mathfrak{temp} temp
(以上均为口胡,没有找到题目,不保证正确性)

现在问题到了环上就不好这么想了。

假设第 i \mathfrak{i} i个人给第 j \mathfrak{j} j个人传递了 x i , j \mathfrak{x_{i,j}} xi,j
实际上没有必要,因为一个人直接地只会传给一个人
设第 i \mathfrak{i} i个人给第 ( i    m o d    n ) + 1 \mathfrak{(i\;mod\;n)+1} (imodn)+1个人传递了 x i \mathfrak{x_i} xi(反过来也行)
有: a n s = ∑ i = 1 n ∣ x i ∣ \mathfrak{ans=\sum\limits_{i=1}^n{|x_i|}} ans=i=1nxi
这还不够。如果规定了这样的方向,那么有:第 i \mathfrak{i} i个人最后的值为 a i − x i + x i − 1 = a ‾ \mathfrak{a_i}-\mathfrak{x_i}+\mathfrak{x_{i-1}}=\mathfrak{\overline{a}} aixi+xi1=a
(不单独给 n → 1 \mathfrak{n}\to 1 n1分类了,知道就好)

然后这个可以列 n − 1 \mathfrak{n-1} n1个式子消掉 n − 1 \mathfrak{n-1} n1 x \mathfrak{x} x
它们都可以表示为形如: x j = x ∀ i + ξ j x_j=\mathfrak{x_{\forall i}+\xi_j} xj=xi+ξj

a 1 − x 1 + x n = a ‾ ⋯ x 1 = a 1 + x n − a ‾ = a 1 + x n − a ‾ \mathfrak{a_1-x_1+x_n=\overline{a}\quad\cdots\quad x_1=a_1+x_n-\overline{a}=a_1+x_n-\overline{a}} a1x1+xn=ax1=a1+xna=a1+xna
a 2 − x 2 + x 1 = a ‾ ⋯ x 2 = a 2 + x 1 − a ‾ = a 1 + a 2 + x n − 2 a ‾ \mathfrak{a_2-x_2+x_1=\overline{a}\quad\cdots\quad x_2=a_2+x_1-\overline{a}=a_1+a_2+x_n-2\overline{a}} a2x2+x1=ax2=a2+x1a=a1+a2+xn2a
a 3 − x 3 + x 2 = a ‾ ⋯ x 3 = a 3 + x 2 − a ‾ = a 1 + a 2 + a 3 + x n − 3 a ‾ \mathfrak{a_3-x_3+x_2=\overline{a}\quad\cdots\quad x_3=a_3+x_2-\overline{a}=a_1+a_2+a_3+x_n-3\overline{a}} a3x3+x2=ax3=a3+x2a=a1+a2+a3+xn3a
    ⋮ \qquad\qquad\qquad\qquad\;\,\vdots
⋯        ​ ⋯ x n − 1 = x n − ( n − 1 ) a ‾ + ∑ i = 1 n − 1 a i \qquad\quad\cdots\quad\;\;\ \!\quad\quad\cdots\quad\mathfrak{x_{n-1}=x_n-(n-1)\overline{a}+\sum\limits_{i=1}^{n-1}a_i}  xn1=xn(n1)a+i=1n1ai

a n s = ∣ x n ∣ + ∑ i = 1 n − 1 ∣ x n − i a ‾ + ∑ j = 1 i a j ∣ \mathfrak{ans=|x_n|+\sum\limits_{i=1}^{n-1}|x_n-i\overline{a}+\sum\limits_{j=1}^i}a_j| ans=xn+i=1n1xnia+j=1iaj
由此可得要使 a n s \mathfrak{ans} ans最小就得让 x n \mathfrak{x_n} xn满足某种条件

注意到 a n s = ∑ i = 1 n ∣ x n − F i ∣ \mathfrak{ans=\sum\limits_{i=1}^n{|x_n-F_i|}} ans=i=1nxnFi要使 a n s \mathfrak{ans} ans最小
所以取中位数。

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int n;
long long x,pre=0,a[1000005]={},aver=0;
long long delta[1000005]={},midpos,deltamid,ans=0;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%lld",&a[i]),aver+=a[i];
	aver/=n;
	for(int i=1;i<=n;++i)
	{
		pre+=a[i];
		if(i<n)delta[i]=i*aver-pre;
	}
	sort(delta+1,delta+n);
	deltamid=delta[1]+delta[n]>>1;
	midpos=(n&1)?delta[n+2>>1]:((abs(deltamid-delta[n>>1])<abs(deltamid-delta[n+2>>1]))?(n>>1):(n+2>>1));
	for(int i=1;i<n;++i)ans+=abs(delta[i]-delta[midpos]);
	printf("%lld",abs(delta[midpos])+ans);
	return 0;
}

你可能感兴趣的:(BZOJ,结论)