IOI2011ricehub米仓

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

    一个整数 最多稻米数

Solution

    同样的二分答案,不同的是这里的检验需要在纸上画图推算一下。这里是枚举区间的左至点,用公式推出花费。

Code

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 using namespace std;
 5 int r,l;
 6 long long b;
 7 long long x[100011],f[100011];
 8 
 9 bool check(int num)
10 {    
11     int j,m;
12     long long sum;
13     for (int i=1; i<=r-num+1; i++)
14     {
15         j=i+num-1; m=(i+j)/2;
16         sum=x[m]*(m-i)-(f[m-1]-f[i-1])+(f[j]-f[m])-x[m]*(j-m);//一个神奇的公式
17         if (sum<=b) return true; 
18     }
19     return false;
20 }
21 
22 int main()
23 {
24     cin>>r>>l>>b; f[0]=0;
25     for (int i=1; i<=r; i++)
26     {
27       cin>>x[i];
28       f[i]=f[i-1]+x[i];
29     } 
30     int left=1,right=r;
31     int mid,ans=1;
32     while (left<=right)//二分
33     {
34         mid=(left+right)/2;
35         if (check(mid)) {if (ans<mid) ans=mid; left=mid+1;}
36           else right=mid-1;
37     }
38     cout<<ans<<endl;
39     return 0;
40 } 

Source

    http://www.lydsy.com/JudgeOnline/problem.php?id=2600

posted @ 2016-12-19 11:42  xzy12138  阅读(220)  评论(1编辑  收藏  举报