1. 程式人生 > >【BZOJ 2600】【IOI 2011】ricehub(貪心+中位數)

【BZOJ 2600】【IOI 2011】ricehub(貪心+中位數)

拿到這道題一開始有兩個naive的想法

想法1:對於每個位置 向右擴充套件 直到不能取了為之 但是又覺得複雜度不對就放棄了......
想法2:離散化座標 二分倉庫的位置 每次往左右兩邊數量較多的一邊靠(這是什麼口胡玩意兒???)

正解:

事實證明我是被ioi2011嚇到了

其實就是想法1加了一丟丟東西 維護一個左指標 右指標 假設是[l,r]區間 那麼倉庫放的位置最優一定是中位數的地方 這樣列舉l的話 r是單調遞增的

然後注意奇奇怪怪的邊界

#include<bits/stdc++.h>
#define N 100005
#define int long long
using namespace std;
template<class T>
inline void read(T &x)
{
    x=0;
    static char ch=getchar();
    while(ch<'0'||ch>'9')   ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
int R,L,B,x[N],sum[N];
int l,r,ans;
inline int check(int l,int r)
{
    int m=(l+r)>>1;
    int sum1=sum[r]-sum[m]-(r-m)*x[m];
    int sum2=x[m]*(m-l)-(sum[m-1]-sum[l-1]);
    return sum1+sum2;   
}
main()
{
    read(R),read(L),read(B);
    for(int i=1;i<=R;i++)   read(x[i]),sum[i]=sum[i-1]+x[i];
    for(l=1;l<R;l++)
    {
        while(r<R&&check(l,r+1)<=B) r++;    //拓展右指標 
        ans=max(ans,r-l+1);
    }
    cout<<ans;
    return 0;
}