【NOIP提高组】运输妹子

5 篇文章 0 订阅

Description

小轩轩是一位非同一般的的大农(lao)场(si)主(ji),他有一大片非同一般的农田,并且坐落在一条公路旁(可以认为是数轴),在他的农田里种的东西也非同一般——不是什么水稻小麦,而是妹子。
在小轩轩的细心培育下,他的大片农田都要结出妹子啦!但是他的农田分布实在是太广阔了,他担心自己的妹子会令路过的人想入非非,于是他想要把所有农田上的妹子都集中到一个仓库里面,贮存起来。可是妹子太多,他叫来了一辆卡车,这辆卡车刚好可以装满一个农田的妹子,并且在满载的情况下,运满满一卡车妹子走1米的费用是1元。由于小轩轩技术精湛,他的每个农田产量都是一样的。即把一个农田的妹子都运到仓库费用为农田与仓库坐标差值的绝对值。理想很美好,但现实很残酷——小轩轩还没有想好在什么位置搭建他的仓库,而且他的运输费用是有限的。
请你帮忙计算一下,在什么位置搭建仓库,使得小轩轩能收获的妹子最多。(仓库的位置可与农田的位置重合,并且在公路长度范围内)。

Data Constraint

对于 30% 的数据,N≤1000,L≤10000。
对于 60% 的数据,N≤10000,L≤1000000。
对于 100% 的数据,N≤100000,L≤1000000000,W≤2000000000000000。

Solution

看到数据范围首先要有的一个思想就是二分答案,显然求最值是满足二分性质的。其次还要发现一个性质,能够被收获的农田一定是连续的,不存在有断开的答案会更优。计算发现,条件就是求所有点到中点的距离和要小于等于要求,一个个算一定会超时,如何O(1)算出?显然对于任意两个在中点异侧的点,代价就是两点坐标差,那么把中点两侧的坐标和都算出来之后计算差值。

Code

var
    a:array[0..100005] of longint;
    f:array[0..100005] of int64;
    n,m,i,ans,l,r,mid:longint;
    w,t:int64;
procedure qsort(l,r:longint);
var i,j,mid:longint;
begin
    i:=l;j:=r;
    mid:=a[(i+j)div 2];
    repeat
        while a[i]<mid do inc(i);
        while mid<a[j] do dec(j);
        if i<=j then
        begin
            a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
            inc(i); dec(j);
        end;
    until i>j;
    if i<r then qsort(i,r);
    if l<j then qsort(l,j);
end;
function pd(x:longint):boolean;
var i,j,k,l:longint;
begin
    for i:=1 to n-x+1 do
    begin
        j:=i+x-1; t:=0;
        k:=i+(j-i)div 2;l:=j-(j-i)div 2;
        if (j-i)mod 2=1 then t:=t+(f[j]-f[l-1])-(f[k]-f[i-1])
        else t:=t+(f[j]-f[l])-(f[k-1]-f[i-1]);
        if t<=w then exit(true);
    end;
    exit(false);
end;
begin
    readln(n,m,w);
    for i:=1 to n do readln(a[i]);
    qsort(1,n);
    for i:=1 to n do f[i]:=f[i-1]+a[i];
    l:=1;r:=n;
    while l<r do
    begin
        mid:=(l+r) div 2;
        if pd(mid) then
        begin
            ans:=mid;
            l:=mid+1;
        end else r:=mid-1;
    end;
    if pd(l) then ans:=l;
    writeln(ans);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值