天天寫演算法之interview
阿新 • • 發佈:2019-02-15
直接上思路,問需要m個檢察官,才能剛好得m個區間的最大值,使其加和能夠大於要求的n
最好的情況下,我們先求出需要max,然後用n/max,這樣就是最好的情況,其他的情況都在這個情況的基礎上進行的。在這個基礎上,每次組數+1,看啥時候能大於n,直接跳出。OK這裡知道了有一個迴圈,是n的,然後需要找n個區間的最值。如果是暴力的話,那麼這個的複雜度是n^2級的。沒有嘗試,而資料量是上萬級的。那麼就會超時。所以就用到了ST演算法(RMQ)。一種離線演算法,採用dp,分治的思想來進行處理。事先把所有的結構都計算出來,最後查詢都是O(1)複雜度的。OK,上程式碼:上一個ST演算法的連線,點選開啟連結講的很不錯。繼續努力
最好的情況下,我們先求出需要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 ; }