bzoj 2600: [Ioi2011]ricehub

2600: [Ioi2011]ricehub

Description

乡间有一条笔直而长的路称为“米道”。沿着这条米道上 R 块稻田,每块稻田的坐标均
为一个 1 到 L 之间(含 1 和 L)的整数。这些稻田按照坐标以不减的顺序给出,即对于 0 ≤ i <
R,稻田 i 的坐标 X[i]满足 1 ≤ X[0] ≤ ... ≤ X[R-1] ≤ L。 
注意:可能有多块稻田位于同一个坐标上。 
我们计划建造一个米仓用于储存尽可能多的稻米。和稻田一样,米仓将建在米道上,其
坐标也是一个 1 到 L 之间的整数(含 1 和 L)。这个米仓可以建在满足上述条件的任一个位
置上,包括那些原来已有一个或多个稻田存在的位置。 
在收获季节,每一块稻田刚好出产一滿货车的稻米。为了将这些稻米运到米仓,需要雇
用一位货车司机来运米。司机的收费是每一满货车运送一个单位的距离收取 1 元。換言之,
将稻米从特定的稻田运到米仓的费用在数值上等于稻田坐标与米仓坐标之差的绝对值。 
不幸的是,今年预算有限,我们至多只能花费 B 元运费。你的任务是要帮我们找出一个
建造米仓的位置,可以收集到尽可能多的稻米。 

Input

第一行 三个整数 R L B
接下来R行 每行一个整数 表示X[i]

Output

一个整数 最多稻米数

Sample Input

5 20 6
1
2
10
12
14

Sample Output

3
HINT
1 ≤ R ≤ 100,000
1 ≤ L ≤ 1,000,000,000
0 ≤ B ≤ 2,000,000,000,000,000
 
题解:
 
二分答案裸题。。
 
不过在算花费的时候有点搞脑子。自己推一推就行了。
#include<stdio.h>
#include<iostream>
using namespace std;
#define ll long long
int n,m,i,mid,l,r,x,L,R,a[100005];
ll s,ans,B;
inline void read(int &v){
    char ch,fu=0;
    for(ch='*'; (ch<'0'||ch>'9')&&ch!='-'; ch=getchar());
    if(ch=='-') fu=1, ch=getchar();
    for(v=0; ch>='0'&&ch<='9'; ch=getchar()) v=v*10+ch-'0';
    if(fu) v=-v;
}
int main()
{
    cin>>n>>m>>B;
    for(i=1;i<=n;i++) read(a[i]);
    l=0;r=n;
    while(l<=r)
    {
        mid=(l+r)>>1;
        s=0;
        x=mid/2+1;
        L=1;R=mid;
        for(i=1;i<x;i++) s+=a[x]-a[i];
        for(i=x+1;i<=mid;i++) s+=a[i]-a[x];
        ans=s;
        for(i=2;i<=n-mid+1;i++)
        {
            s-=a[x]-a[L];
            s+=(ll)(a[x+1]-a[x])*(x-L);
            s+=(ll)(a[x]-a[x+1])*(R-x-1);
            s+=a[R+1]-a[x+1]-a[x+1]+a[x];
            ans=min(ans,s);
            L++;R++;x++;
        }
        if(ans<=B) l=mid+1;else r=mid-1;
    }
    cout<<r;
    return 0;
}

  

 

 
 
posted @ 2016-07-14 18:45  lwq12138  阅读(238)  评论(0编辑  收藏  举报