Interviewe HDU - 3486 (ST表+枚举 )(非二分,看下这个数据、)
YaoYao has a company and he wants to employ m people recently. Since his company is so famous, there are n people coming for the interview. However, YaoYao is so busy that he has no time to interview them by himself. So he decides to select exact m interviewers for this task.
YaoYao decides to make the interview as follows. First he queues the interviewees according to their coming order. Then he cuts the queue into m segments. The length of each segment is , which means he ignores the rest interviewees (poor guys because they comes late). Then, each segment is assigned to an interviewer and the interviewer chooses the best one from them as the employee.
YaoYao’s idea seems to be wonderful, but he meets another problem. He values the ability of the ith arrived interviewee as a number from 0 to 1000. Of course, the better one is, the higher ability value one has. He wants his employees good enough, so the sum of the ability values of his employees must exceed his target k (exceed means strictly large than). On the other hand, he wants to employ as less people as possible because of the high salary nowadays. Could you help him to find the smallest m?
Input
The input consists of multiple cases.
In the first line of each case, there are two numbers n and k, indicating the number of the original people and the sum of the ability values of employees YaoYao wants to hire (n≤200000, k≤1000000000). In the second line, there are n numbers v1, v2, …, vn (each number is between 0 and 1000), indicating the ability value of each arrived interviewee respectively.
The input ends up with two negative numbers, which should not be processed as a case.
Output
For each test case, print only one number indicating the smallest m you can find. If you can’t find any, output -1 instead.
Sample Input
11 300
7 100 7 101 100 100 9 100 100 110 110
-1 -1
Sample Output
3
Hint
We need 3 interviewers to help YaoYao. The first one interviews people from 1 to 3, the second interviews people from 4 to 6,
and the third interviews people from 7 to 9. And the people left will be ignored. And the total value you can get is 100+101+100=301>300.
题意:
给你n个人的能力值,和一个数值k,让你求一个最小的m,使其把n个人分成 floor(n/m) 个块,每一个块中最大值加起来的sum和严格的大于k 。
思路:
本认为是一个rmq+二分的题目,但是因为如果分块的最后还剩下人,那些人将被直接忽略,导致并没有二分的单调性质。
也可以看下这组数据:
8 282
69 27 64 87 37 40 21 28
答案应该是 5
二分对这组数据是无能为力的。
那么我们根据k值数组中的最大值来判断最小需要多少个面试官来枚举,,,又因为数据太弱,所以可以直接过。
我们用ST表来预处理数组后,O(1) 询问区间最值。
细节见代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2) { ans = ans * a % MOD; } a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int *p);
const int maxn = 200010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int a[maxn];//原始输入数组
int st[maxn][25];//st表
void init(int n)
{
for (int i = 0; i < n; i++)
st[i][0] = a[i];
for (int i = 1; (1 << i) <= n; i++)
{
for (int j = 0; j + (1 << i) - 1 < n; j++)
st[j][i] = max(st[j][i - 1],st[j + (1 << (i - 1))][i - 1]);
}
}
int query(int l, int r)
{
int k = (int)(log((double)(r - l + 1)) / log(2.0));
return max(st[l][k],st[r - (1 << k) + 1][k]);
}
int n;
ll k;
ll check(int mid)
{
int num=n/mid;
ll res=0ll;
int l,r;
l=0;
r=num-1;
repd(i,1,mid)
{
res+=1ll*query(l,r);
l+=num;
r+=num;
}
return res;
}
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
gbtb;
while(cin>>n>>k)
{
if(n<0)
{
break;
}
// ll
rep(i,0,n)
{
cin>>a[i];
}
init(n);
int l=1;
int r=n;
int mid;
int ans=-1;
int x=max(1ll,k/max(1,query(0,n-1)));
repd(i,x,n)
{
if(check(i)>k)
{
ans=i;
break;
}
}
cout<<ans<<endl;
}
return 0;
}
inline void getInt(int *p)
{
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
} else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}