IOI2011 ricehub

来源:互联网 发布:神农架值不值得去 知乎 编辑:程序博客网 时间:2024/05/22 12:45

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_backusing 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;}
0 0
原创粉丝点击