DTOJ 1561: 草堆擺放
題目描述
FJ買了一些乾草堆,他想把這些乾草堆分成N堆(1<=N<=100,000)擺成一圈,其中第i堆有B_i數量的乾草。不幸的是,負責運貨的司機由於沒有聽清FJ的要求,只記住分成N堆擺成一圈這個要求,而每一堆的數量卻是A_i(1<=i<=N)。當然A_i的總和肯定等於B_i的總和。
FJ可以通過移動乾草來達到要求,即使得A_i=B_i,已知把一個乾草移動x步需要消耗x數量的體力,相鄰兩個乾草堆之間的步數為1。
請幫助FJ計算最少需要消耗多少體力才能完成任務。
輸入
第一行輸入一個整數N。
接下來N行,每行兩個整數,其中第i+1行描述A_i和B_i(1<=A_i,B_i<=1000)。
輸出
輸出一個數表示最少需要消耗的體力。
樣例輸入
4
7 1
3 4
9 2
1 13
樣例輸出
13
提示
【樣例說明】
從第1堆中移動6個乾草到第4堆,從第3堆中移動1個乾草到第2堆,從第3堆中移動6個乾草到第4堆中。
分析:
思維好題。完全沒想到,看了題解的思路才明白。
設$f_i$表示$i->i+1$運了$f_i$堆稻草,$f_n$表示$n->1$運了$f_n$堆。
那麼有:
$a_1-f_1+f_n=b_1$
$a_2-f_2+f_1=b_2$
$a_3-f_3+f_2=b_3$
………
$a_n-f_n+f_{n-1}=b_n$
發現合併後沒有意義,先移項:
$f_1=b_1-a_1+f_n$
$f_2=b_2-a_2+f_1$
$f_3=b_3-a_3+f_2$
………
$f_n=b_n-a_n+f_{n-1}$
將上面的$f_i$向下代入:
$f_1=b_1-a_1+f_n$
$f_2=b_2-a_2+b_1-a_1+f_n$
$f_3=b_3-a_3+b_2-a_2+b_1-a_1+f_n$
………
$f_n=f_n$
那麼我們就得到了$f_i$與$f_n$的關係,取絕對值時改一下符號:
(設$s_i$表示$a_i-b_i$的字首和,$d$表示$f_n$)
$|f_1|=|s_1-|-d||$
$|f_2|=|s_2-|-d||$
$|f_3|=|s_3-|-d||$
…………
$|f_n|=|-d|$
那麼就每個式子就變成了$|x-y|$的形式,那麼問題就是求數軸上每個點到同一個位置的距離最小。那麼就是中位數了。
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define N 100005 using namespace std; int n,a,b,s[N]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&a,&b); s[i]=s[i-1]+a-b; } sort(s+1,s+n+1); int x=-s[(n+1)/2]; long long ans=0; for(int i=1;i<=n;i++) ans+=abs(s[i]+x); printf("%lld\n",ans); return 0; }
思維要好好鍛鍊,加油刷題吧!