Interviewe HDU - 3486

原题链接
考察:枚举+RMQ
错误思路:
  二分+RMQ,这里不能二分的原因是不能整除的时候,后面超出的是舍弃,舍弃部分可能会使二分答案没有单调性.
正确思路:
  枚举答案,但需要优化,假设每段都可以取到最大值,那么\(>k\)最少需要\(\frac {k+maxn-1}{maxn}\).然后判断是否可行

Code

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 200010,M = 17;
int n, k,w[N],f[N][M],ans[N];
bool check(int mid)
{//分成3个面试官:取3个人 
    int len = n / mid, sum = 0;
    int c = log(len) / log(2);
    int cnt = 0;
    for (int i = 1; i <= n;)
    {
        int r = i + len - 1;
        if(r>n) break;
        ans[++cnt] = max(f[i][c],f[r-(1<<c)+1][c]);
        i = r + 1;
    }
    sort(ans+1,ans+cnt+1);
    for(int i=cnt;i>=cnt-mid+1;i--)
    	sum+=ans[i];
    return sum > k;
}
void init()
{
	memset(f,0,sizeof f);
    for (int j = 0; j < M;j++)
        for (int i = 1; i+ (1<<j)-1 <= n;i++)
          if(!j)
              f[i][j] = w[i];
          else
              f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
}
int main()
{
    while(scanf("%d%d",&n,&k)!=EOF&&n!=-1)
    {
    	int maxn = 0,st = 1,ans = -1;
        for (int i = 1; i <= n;i++) scanf("%d", &w[i]),maxn = max(w[i],maxn);
        init(); 
        if(maxn) st = (k+maxn-1)/maxn;
        for(int i = st;i<=n;i++)
        {
        	if(check(i))
        	{
        		ans = i;
        		break;
			}
		}
		printf("%d\n",ans);
    }
    return 0;
}

posted @ 2021-07-03 22:32  acmloser  阅读(23)  评论(0编辑  收藏  举报