用線段樹維護:點擊打開鏈接
用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;
}