BZOJ1045 HAOI2008糖果传递(贪心)
生活随笔
收集整理的這篇文章主要介紹了
BZOJ1045 HAOI2008糖果传递(贪心)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
顯然最后每個小朋友所擁有的糖果數就是糖果數總和的平均數。設該平均數為t。
環的問題一般斷成鏈,但這個題似乎沒有什么很好的辦法在枚舉斷點的時候快速算出答案(我甚至不知道會不會有斷點)
于是我們假裝把他斷開了。假裝現在我們已經知道了1號小朋友要給n號小朋友x顆糖果(可以為負)。那么,2給1,3給2,4給3,等等等等,小朋友之間傳遞的糖果數都被確定了。
1號給了n號x顆后,其還剩a1-x顆,那么2號小朋友就要給1號t-(a1-x)=x-(a1-t)顆。
把1、2號看成整體,給了n號x顆后,其還剩a1+a2-x顆,那么3號小朋友就要給他們x-[(a1+a2)-t*2]顆。
以此類推,k號小朋友要給k-1號x-[(a1+a2+……+ak-1)-t*(k-1)]顆。
我們的目標是使上面所有數的絕對值之和最小。與這個值有關的量里只剩x是變量了。
那么什么時候這個值最小?假裝這有一個數軸,有一些點是0,a1-t,(a1+a2)-t*2,等等等等。
我們要找一個點x使得其到這些點的距離之和最小。顯然放在最中間,也就是中位數的位置就行了。
stl里有個nth_element的黑科技,線性找第k大。
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() {int x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();return x*f; } #define N 1000010 int n; long long a[N],s[N],k,ans=0; int main() {n=read();for (int i=1;i<=n;i++) s[i]=s[i-1]+read();k=s[n]/n;for (int i=1;i<=n;i++) a[i]=s[i-1]-k*(i-1);nth_element(a+1,a+(n+1>>1),a+n+1);for (int i=1;i<=n;i++) ans+=abs(a[i]-a[n+1>>1]);cout<<ans;return 0; }?
轉載于:https://www.cnblogs.com/Gloid/p/9404104.html
總結
以上是生活随笔為你收集整理的BZOJ1045 HAOI2008糖果传递(贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图片滤镜
- 下一篇: 微信支付 签名算法 sign node实