[dp] bzoj1045: [HAOI2008] 糖果传递

版权声明:本文为QQQQqtt原创,但是我猜没有人转载oAo https://blog.csdn.net/qq_36038511/article/details/80881715

bzoj1045: [HAOI2008] 糖果传递:https://www.lydsy.com/JudgeOnline/problem.php?id=1045

这是一个环形的均分糖果问题

证法1:
用s[i]记录a[i+1]给a[i]的糖果个数 
∵s[i]=t-a[i]+s[i-1]
∴t=a[i]+s[i]-s[i-1]
当i=2 
a[2]-s[1]+s[2]=t s[2]=t-a[2]+s[1]
当i=3
a[3]-s[2]+s[3]=t s[3]=t-a[3]+s[2]=t-a[3]+(t-a[2]+s[1])=2t-a[3]-a[2]+s[1]
设f[1]=0 f[2]=a[2]-t f[3]=a[2]-t-a[3]-t=f[2]-a[3]-t f[i]=f[i-1]+a[i]+t
则 s[i]=s[1]-f[i]
ans=sigma(abs(s[1]-f[i])) {i|1<=i<=n}
此柿子的几何意义为找一个点 使f[i]对应的点到这个点的距离总和最小  所以s[1] 应为中位数 

证法2:
用s[i]记录a[i]和t的差值 并求前缀和
这是一个环 将环拆为以k为开头的一条链
对于每一个s[i] 如果>0 则要传出糖果 如果<0 则要传入糖果

对于原来k后面的(i>k)  代价=s[i]-s[k]
对于原来k前面的(i<k)  代价=s[i]+s[n]-s[k] (=s[k~n]+s[1~i])
而s[n]恒等于0(题目保证能够均分)
ans=sigma(abs(s[i]-s[k]))  {i,k|1<=i<=n,1<=k<=n} 
此柿子的几何意义为找一个点 使s[i]对应的点到这个点的距离总和最小  所以s[k] 应为中位数 

大神:这种题不都一眼切啊我都直接精A了
来弱弱地存个证明的档

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
long long a[1100000],s[1100000];
int main()
{
    /*


    */
    long long t=0;
    int n;
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        t+=a[i];
    }
    t/=n;
    for (int i=1;i<=n;i++) s[i]=a[i]-t+s[i-1];
    sort(s+1,s+1+n);
    long long ans=0,x;
    if (n%2==1) x=s[n/2+1];
    else x=(s[n/2]+s[n/2+1])/2;
    for (int i=1;i<=n;i++)
    {
        ans+=abs(s[i]-x);
    }
    printf("%lld\n",ans);
    return 0;
}

这个故事告诉我们糖果传递并不是水题(哭)
这个故事告诉我们糖果传递并不是水题(哭)

猜你喜欢

转载自blog.csdn.net/qq_36038511/article/details/80881715