hdu 3484 Interviewe RMQ+二分

本文介绍了一种利用预处理技术实现区间最大值快速查询的方法,并结合二分搜索来寻找满足条件的最佳分割数量。通过构建特殊的数据结构,可以在对数时间内找到区间内的最大值,进而解决特定的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5 const int maxn = 200000 + 5;
 6 int a[maxn];
 7 int maxsum[maxn][30];
 8 int n, k;
 9 
10 void RMQ(int num){
11     for (int i = 1; i <= num; i++){
12         maxsum[i][0] = a[i];
13     }
14 
15     for (int j = 1; j < 30; j++){
16         for (int i = 1; i <= num; i++){
17             if (i + (1 << j) - 1 <= num){
18                 maxsum[i][j] = max(maxsum[i][j - 1], maxsum[i + (1 << (j - 1))][j - 1]);
19             }
20         }
21     }
22     return;
23 }
24 
25 //获取[x,y]的最大值
26 int getmax(int x, int y){
27     int k1 = (int)(log((double)(y - x + 1)) / log(2.0));
28     return max(maxsum[x][k1], maxsum[y - (1 << k1) + 1][k1]);
29 }
30 
31 //获取m人的最大值(m组)
32 int Find(int m){
33     int ans = 0;
34     int num = n / m;//每组num个人
35     for (int i = 0; i < m; i++){
36         ans += getmax(1 + i*num, (i + 1)*num);
37         if (ans > k)
38             return ans;
39     }
40     return ans;
41 }
42 
43 int main(){
44     while (~scanf("%d%d", &n, &k)){
45         if (n == -1 && k == -1)
46             break;
47         int sum = 0;
48         bool ok_1 = false;
49         for (int i = 1; i <= n; i++){
50             scanf("%d", &a[i]);
51             if (a[i] > k){
52                 ok_1 = true;
53             }
54             sum += a[i];
55         }
56         if (ok_1){
57             printf("1\n");
58             continue;
59         }
60         if (sum < k){
61             printf("-1\n");
62             continue;
63         }
64         if (sum == k){
65             printf("%d\n", k);
66             continue;
67         }
68         //初始化
69         RMQ(n);
70         bool ok = false;
71         int l = 1;
72         int r = n;
73         int ans = 0;
74         int mid, t;
75         while (l <= r){
76             mid = (l + r) / 2;
77             t = Find(mid);
78             if (t > k){
79                 r = mid - 1;
80                 ans = mid;
81                 ok = true;
82             }
83             else{
84                 l = mid + 1;
85             }
86         }
87         if (ok)
88             printf("%d\n", ans);
89         else
90             printf("-1\n");
91     }
92     //system("pause");
93     return 0;
94 }

 

转载于:https://www.cnblogs.com/ouyang_wsgwz/p/7846465.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值