题目思路:
一开始看感觉像是要二分 但是单调性不是很确定 看到有大佬给了不满足单调性的数据 看了题解才晓得原来直接枚举就能做
先做前缀和来判断是否一定有解
然后找区间个数的边界
右边界很简单 就是n
拿k+1(题目要求严格大于k)除数组里面的最大的数 得到的值就是最小的区间个数 即左边界了
然后用rmq查询区间最大值再相加比较即可
中间有些小细节要注意
不然会报 Runtime Error(INTEGER_DIVIDE_BY_ZERO)
ac代码:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 2e5+50;
const int inf = 0x1f1f1f1f;
const int mod = 2333;
int n,k,a[maxn],dp[maxn][25],sum[maxn];
void rmq()
{
for(int i=1;i<=n;i++)
dp[i][0]=a[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int query(int l,int r)
{
int i=0;
while(l+(1<<i)-1<r)
{
i++;
}
i--;
return max(dp[l][i],dp[r-(1<<i)+1][i]);
}
int main()
{
while(~scanf("%d%d",&n,&k))
{
if(n==-1&&k==-1) break;
sum[0]=0;
int maxx=1;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
maxx=max(maxx,a[i]);
}
if(sum[n]<=k)
{
printf("-1\n");
continue;
}
rmq();
int l=(k+1)/maxx;
if(l==0) l=1;//这里一定要注意 没有这一步的话 l可能会是0 在下面tem=n/i;那里就会出问题然后报之前提到的那个错误
int r=n;
int sum111,ans=n;//这里如果写ans=-1的话会wa 当答案应该为n的时候会输出-1 令人头疼 这个地方让我wa到自闭
for(int i=l;i<=r;i++)
{
sum111=0;
int tem=n/i;
for(int j=0;j<i;j++)
{
sum111+=query(1+j*tem,tem+tem*j);
if(sum111>k)break;
}
if(sum111>k)
{
ans=i;
break;
}
}
printf("%d\n",ans);
}
}