Task:
n块稻田,每块稻田一个位置pi,稻田位置可能重叠.现在可以设置一个米仓,一块稻田运送粮食的代价就是运送的距离,现在给出花费t,求出在t内最多能运送多少粮食.
n≤1e5,pi≤1e9,t≤2e15.
Solution:
假如米仓的位置确定,可以确定最后选中的答案一定是最接近米仓的一段区间.而且左右端点到米仓的距离会尽可能接近.
=>假如最后的区间确定,那么米仓的位置就是其中点.
那么就可以枚举这个区间(l,r),很容易就发现对于同一个l,r具有二分的性质.因此直接枚举一维+二分一维即可.复杂度O(nlogn)
当然尺取也可以解决.复杂度为O(n).
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<map>
#include<set>
#define ll long long
#define y1 abcdedhf
#define pb push_back
using namespace std;
inline void rd(int &res){
res=0;char c;
while(c=getchar(),c<48);
do res=(res<<1)+(res<<3)+(c^48);
while(c=getchar(),c>=48);
}
const int M=1e5+5;
ll m;
int ans=0;
int L,n,A[M];
ll sum[M];
bool chk(int st,int en){
int mid=(st+en)>>1;//mid就是建立谷仓的地方
ll cost=1ll*A[mid]*(mid-st+1)-sum[mid]+sum[st-1]+sum[en]-sum[mid]-1ll*A[mid]*(en-mid);
if(cost<=m){
return true;
}
return false;
}
int main(){
int i,j,k;
rd(n);rd(L);cin>>m;
for(i=1;i<=n;i++){
rd(A[i]);
sum[i]=sum[i-1]+A[i];
}
int r=1;
for(i=1;i<=n;i++){//枚举左端点
while(r<=n&&chk(i,r))r++;
ans=max(ans,r-i);
}
cout<<ans<<endl;
return 0;
}