题意:
瑶瑶有一家有一家公司,最近他想招m个人。因为他的公司是如此的出名,所以有n个人来参加面试。然而,瑶瑶是如此忙,以至于没有时间来亲自面试他们。所以他准备选择m场面试来测试他们。
瑶瑶决定这样来安排面试。首先,他把这些面试者按照来到的顺序排成一队。然后,他把这个队列切成m段。每段的长度是[n/m](向下取整),这意味着他将忽略掉剩下的人。然后,他将选择每一段里面最好的那个人。
瑶瑶的想法看起来很有趣,但是他遇到了另外的问题。他把每个人的能力赋了一个值。值越大的越好。他希望员工足够的好,这样,他们的和可以达到他的目标k(严格大于)。另一方面,因为现在高昂的工资,他希望员工的数量尽可能少。
你能帮他找出最小的m吗?
思路:
Sparse Table + 枚举区间长度。
枚举区间个数会TLE,不懂为什么,代码也有点没看懂。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cmath> 5 6 using namespace std; 7 8 const int MAXN = (int)2e5+5; 9 10 int ST[21][MAXN]; //Sparse Table 11 int hight[MAXN]; 12 int n, k; 13 14 inline int topBit(int x) { 15 return (int) (log((double)x)/log(2.0)); 16 } 17 18 inline int Query(int L, int R) { 19 int h = hight[R-L]; 20 if ((R-L) < (1<<h)) h -= 1; 21 return max(ST[h][L], ST[h][R-(1<<h)]); 22 } 23 24 int main() { 25 #ifdef Phantom01 26 freopen("CSU1364.in", "r", stdin); 27 #endif // Phantom01 28 29 memset(hight, 0, sizeof(hight)); 30 for (int i = 1; i < MAXN; i++) //比他左位移一位的数高一 31 hight[i] = hight[i>>1] + 1; 32 33 while (scanf("%d %d", &n, &k)!=EOF) { 34 if (-1==n && -1==k) break; 35 36 for (int i = 0; i < n; i++) 37 scanf("%d", &ST[0][i]); //最下面一层就是原始数据 38 39 int h = hight[n]; 40 for (int i = 1; i <= h; i++) { 41 for (int j = 0; j < n; j++) { 42 if ((j+(1<<(i-1))) < n) 43 ST[i][j] = max(ST[i-1][j], ST[i-1][j+(1<<(i-1))]); 44 else 45 ST[i][j] = ST[i-1][j]; 46 } 47 } 48 int ans = -1; 49 for (int i = n; i > 0; i--) { 50 int m = n/i; 51 int tmp = 0; 52 for (int j = 0; j < m; j++) { 53 tmp += Query(j*i, (j+1)*i); 54 if (tmp>k) { 55 ans = j+1; //不知道这里为啥是j+1而不是 m 56 break; 57 } 58 } 59 if (tmp > k) 60 break; 61 } 62 printf("%d\n", ans); 63 } 64 65 return 0; 66 }