[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
HINT
1 ≤ R ≤ 100,000
1 ≤ L ≤ 1,000,000,000
0 ≤ B ≤ 2,000,000,000,000,000
二分答案
有一个结论,1~len最好的米仓选址肯定是len/2
当选址pos移到poss=pos+1时
tot想对于原来有如下变化,假设l~i长度为len,i=len+1~n,显然l=i-len+1
tot-=a[poss-(len&1)]-a[l-1]
tot+=a[i]-a[poss]
这个变化是通过奇偶分类讨论得到,可以画一下
然后就可以O(n)判断是否有<=B的方案
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 typedef long long lol; 7 lol B,a[100001],n,L,as; 8 bool check(lol len) 9 {lol tot=0,pos,i,poss; 10 pos=len/2+(len&1); 11 for (i=1;i<=len;i++) 12 { 13 tot+=abs(a[pos]-a[i]); 14 } 15 if (tot<=B) return 1; 16 for (i=len+1;i<=n;i++) 17 { 18 lol l=i-len+1; 19 poss=pos+1; 20 tot-=abs(a[poss-(len&1)]-a[l-1]); 21 tot+=abs(a[i]-a[poss]); 22 pos=poss; 23 if (tot<=B) return 1; 24 } 25 return 0; 26 } 27 int main() 28 {lol i; 29 cin>>n>>L>>B; 30 for (i=1;i<=n;i++) 31 scanf("%lld",&a[i]); 32 lol l=1,r=n; 33 while (l<=r) 34 { 35 lol mid=(l+r)/2; 36 if (check(mid)) as=mid,l=mid+1; 37 else r=mid-1; 38 } 39 cout<<as; 40 }