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;
}
原文地址:https://www.cnblogs.com/magisk/p/8762528.html