A- zcf昨天爆零了吗
签到,过。
C- 睿智的zcf
题目:假设实验室按比赛排名顺序先选择了n个人,每个人有一个能力值,代表了代码能力的强弱,然后学长要把这些人分成m段,如果不能整除(n/m)多出来就后面的人就不要了,然后从这m段里面选择每段的最大能力值加起来看是否能够大于老板需要的目标k由于实验室位置有限,所以实验室要尽可能少录取人,所以zcf学长想让你找出满足条件的最小的m。
- RMQ+枚举
- 枚举每种长度的区间的情况,RMQ求最值并且求和
- 对应代码
#include<bits/stdc++.h>
using namespace std;
const int mx = 200000+10;
int dmax[mx][20];
void initmax(int n, int d[])
{
for(int i=1; i<=n; i++)
dmax[i][0] = d[i];
for(int j=1; (1<<j)<=n; j++)
for(int i=1; i+(1<<j)-1<=n; i++)
dmax[i][j] = max(dmax[i][j-1], dmax[i+(1<<(j-1))][j-1]);
}
int getmax(int L, int R)
{
int k=0;
while((1<<(k+1))<=R-L+1) k++;
return max(dmax[L][k], dmax[R-(1<<k)+1][k]);
}
int main()
{
int n, k;
while(scanf("%d%d", &n, &k) && (n+k)>0){
int a[mx];
for(int i=1; i<=n; i++)
scanf("%d", &a[i]);
initmax(n, a);
int sum = 0 , bl = 0, m;
for(m=1; m<= n; m++)
{
sum = 0; bl = 0;
int ans = n / m, cnt(0);
for(int i=1; cnt<m ;i+=ans)
{
cnt++;
int A, B;
A = i; B = i+ans-1;
int mxx = getmax(A, B);
sum += mxx;
if(sum > k)
{bl = 1; break;}
}
if(bl) break;
}
if(bl)
printf("%d\n", m);
else
printf("-1\n");
}
return 0;
}