hdu3486 RMQ+二分

用線段樹維護:點擊打開鏈接


用rmq維護的效果好一點

#include<cstdio>
#include<algorithm>
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)

#define maxn 222222
int 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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章