HDU 3486 Interviewe
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3486
题解:用RMQ查询区间最大值,从m为1开始枚举每种情况,但是直接枚举会超时,如果连续两次的N/m相等,就直接取用上次的结果,再加上多出的一段,避免做重复的运算
也有很多提出对m二分。二分能过OJ测评,但是存在问题,因为并不一定是分段越多,总和越大,比如:10 10 100 100 10 10, m=2时和为200,m=3时和为120。
代码如下:
#include <cstdio>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
const int MAX = 2e5+7;
const int INF = 0x3f3f3f3f;
int N, M;
int dp[MAX][30];
string s;
void init() {
for (int i = 0; i < N; i++) {
cin >> dp[i][0];
}
}
void rmq() {
int k = log(N)/log(2.0);
for (int j = 1; j <= k; j++) {
for (int i = 0; i+(1<<j) <= N; i++) {
dp[i][j] = max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
}
}
}
int query(int x, int y) {
int k = log(y-x+1)/log(2.0);
return max(dp[x][k], dp[y-(1<<k)+1][k]);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
while (cin >> N >> M) {
if (N == -1 && M == -1) break;
init();
rmq();
int i, j = 0, n, ans = 0, pre = 0;
for (i = 1; i <= N; i++) {
n = N/i;
if (pre != n) {
j = 0;
ans = 0;
}
for (; j < i; j++) {
ans += query(n*j,j*n+n-1);
}
pre = n;
if (ans > M) break;
}
if (i > N) cout << "-1" << endl;
else cout << i << endl;
}
return 0;
}