hdu3486 RMQ+二分

来源:互联网 发布:crc8校验算法 编辑:程序博客网 时间:2024/05/21 15:40

用线段树维护:点击打开链接


用rmq维护的效果好一点

#include<cstdio>#include<algorithm>using namespace std;#define ls (rt<<1)#define rs (rt<<1|1)#define mid ((l+r)>>1)#define maxn 222222int a[maxn],m,n,k;int lg[maxn],ma[20][maxn];void pre(){lg[0]=-1;for(int i=1;i<maxn;++i)lg[i]=lg[i>>1]+1;}void init(){    memset(ma,0,sizeof ma);    for(int i=1;i<=n;++i)ma[0][i]=a[i];    for(int i=1;i<=lg[n];i++)        for(int j=1;j+(1<<i)-1<=n;j++){            ma[i][j]=max(ma[i-1][j],ma[i-1][j+(1<<(i-1))]);        }}int query(int l,int r){    int tmp=lg[r-l+1];    return max(ma[tmp][l],ma[tmp][r-(1<<tmp)+1]);}int scan(){    int res=0,ch;    while(!((ch= getchar())>='0'&&ch<='9')){        if(ch==EOF)return 1<<30;    }    res=ch-'0';    while((ch=getchar())>='0'&&ch<='9')        res=res*10+(ch-'0');    return res;}int judge(int size){    int d=n/size,now,li=d*size,ans=0;    for(int i=1;i<=li;i+=d){        now=query(i,i+d-1);        ans+=now;    }    return ans>k;}int main(){    pre();    while(~scanf("%d%d",&n,&k)){        if(n==-1&&k==-1)break;        int tot=0,ma=0,mi=0;        for(int i=1;i<=n;++i){            a[i]=scan();tot+=a[i];ma=max(a[i],ma);            mi=min(mi,a[i]);        }        pre();        init();                if(tot<k){printf("-1\n");continue;}        if(ma>k){printf("1\n");continue;}                ma=(ma==0)?1:ma;        mi=(mi==0)?1:mi;        int l=1,r=n,ans=-1;        r=min((k/mi+1),n),l=k/ma;        if(l==0)l++;        while(l<=r){            if(judge(mid)){                ans=mid;                r=mid-1;            }else l=mid+1;        }        printf("%d\n",ans);    }    return 0;}


0 0