Usaco Restack

本文分享了解决一道数学竞赛题与算法竞赛题的相似问题,通过巧妙的方法找到解题思路,并用代码实现了解决方案。时间复杂度为O(NlogN+N),适用于对算法与数学结合感兴趣的学习者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在看奥数题的时候,突然发现最后一道题和一道oi题是一样的,看看题目之后(半年之前做的了),很巧妙的,只是我想不起来了。

百度很久~很久~还是找不到题解,最后还是想到了,很激动,很激动~~可怜~发一发~~


Problem: English:: 传送~~http://www.spoj.pl/problems/RESTACK/~~    关键字:: usaco  restack

中文::

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计算最少需要消耗多少体力才能完成任务。


很巧啊~~

设Fi为从i到i+1运Fi堆草, Fn则是n~1运的数量。

有题目得到

A1- F1 + Fn = B1

A2- F2 + F1 = B2

A3- F3 + F2 = B3

............

An- Fn + F1= Bn

要是左边一加, 右边一加, 就全没了~~所以整理式子

F1 = A1- B1 + Fn

F2 = A2- B2 + F1

F3 = A3- B3 + F2

..........

Fn=An- Bn +F1

将每一个式子带入到下一个式子里(最后一个式子除外):

F1 = A1- B1 + Fn

F2 = A2- B2 +A1- B1 + Fn

F3 = A3- B3 + A2- B2 +A1- B1 +Fn

..........

Fn=Fn (特殊处理)【这叫特殊吗???】

就可得到每个F关于Fn的式子啦~~~

加上绝对值后再做一些手脚

|F1|= | A1-B1 - (-Fn) |

|F2|= | SUM(Ai- Bi) - (-Fn) | 1<=i<=2

|F3|= | SUM(Ai- Bi) - (-Fn) | 1<=i<=3

.......

|Fn|=|Fn|

可以看出每个sum(&&&)都是可以提前算出来的, 而 | X - Y |的几何意义为数轴上X的点到Y点的距离。

加起来,得到 (设sum(&&&)= Si , -fn= D)

ANS= |S1- D|+ |S2-D| + |S3-D| + ..... + |Sn-1 - D| + |0 - D|

变成了在数轴上求一个点, 到各点的距离之和最小。

众所周知, 这个点就是这组数据中的中位数(若有偶数个, 取两个点的任意一个都可以)。 不明白请举例子或自行百度。

所以中位数即等于-Fn, 于是得到解决。

时间复杂度O(N log N + N)。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
 
#define N 100005
 
int S[N];
int n;
 
int abs(int x){return (x>0)?x:-x;}
 
int main(){
    scanf("%d",&n);
    int x,y;
    S[0]=0;
    for(int i=1;i<=n;i++) scanf("%d%d",&x,&y), S[i]=S[i-1]+x-y;
    sort(S+1,S+n+1);
    int fn=-S[int(n/2)+1];
    long long Ans=0;
    for(int i=1;i<=n;i++) Ans+=abs(S[i]+fn);
    cout<<Ans<<endl;
    return 0;
}
c 新手 , 程序见笑啦~~~


------------------------------------------End---------------------------------------------------



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值