1. 程式人生 > >天天寫演算法之interview

天天寫演算法之interview

直接上思路,問需要m個檢察官,才能剛好得m個區間的最大值,使其加和能夠大於要求的n
最好的情況下,我們先求出需要max,然後用n/max,這樣就是最好的情況,其他的情況都在這個情況的基礎上進行的。在這個基礎上,每次組數+1,看啥時候能大於n,直接跳出。OK這裡知道了有一個迴圈,是n的,然後需要找n個區間的最值。如果是暴力的話,那麼這個的複雜度是n^2級的。沒有嘗試,而資料量是上萬級的。那麼就會超時。所以就用到了ST演算法(RMQ)。一種離線演算法,採用dp,分治的思想來進行處理。事先把所有的結構都計算出來,最後查詢都是O(1)複雜度的。OK,上程式碼:上一個ST演算法的連線,點選開啟連結講的很不錯。繼續努力
#include <iostream>
#include<cstdio>
#include<string.h>
#include<cmath>
using namespace std;
#define MAX 200010
#define repf(i,from,to) for(int i =from ; i<to ; i++)
int a[MAX];
int f[MAX][20];
struct RMQ{
    void createRMQ(int m)
    {
        repf(i,0,m)
        {
            f[i][0]=a[i];
        }
        for(int j =1 ; (1<<j)<=m;j++)
        {
            for(int i = 0 ; i+(1<<j)-1<m;i++)
            {
                f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
            }
        }
    }
    int searchM(int left ,int right)
    {
        int k = log(right-left+1)/log(2);
        return max(f[left][k],f[right-(1<<k)+1][k]);
    }
}RMQ;

int main(){
    int M,N,Max,Sum;
    while(~scanf("%d%d",&M,&N)&&M>=0&&N>=0)
    {
        Max = Sum =0 ;
        repf(i,0,M)
        {
            scanf("%d",&a[i]);
            Sum+=a[i];
            if(a[i]>Max)
            {
                Max =a[i];
            }
        }

    if(Sum<N)
    {
        printf("-1\n");
        continue ;
    }
    RMQ.createRMQ(M);
    int num_k,k = N/Max;
    int a_sum ;
    if(k==0)
    k = 1 ;
    for(;k<=N;k++)
    {
        num_k = M/k;
        a_sum = 0 ;
        for(int j = 1 ; j <=k;j++)
        {
            a_sum+=RMQ.searchM((j-1)*num_k,j*num_k-1);
        }
        if(a_sum>N)
        {
            break ;
        }
    }

    printf("%d\n",k);
    }
    return 0 ;
}