hdu 3486(RMQ+高效枚举)
来源:互联网 发布:it女神 编辑:程序博客网 时间:2024/09/21 08:58
题意:把n分为 均分为m 段 每段n/m个数字 每段可以选一个最大的数 求这些数相加起来>k的最小的m
解题思路:这道题本来想用二分+rmq的,但discuss里面说二分是错的,所以只能另想别的办法了。
首先是可以肯定的,一定要枚举段数,接下来就是如何减少对内层循环的枚举次数。
当分成i段得到的段长L1 与 之前分成 i-1段得到的段长相同 那就只要把前一次的结果再加上这一次 第i段的最大值 就是当前的结果了 这一步少做了很多步骤 节约了很多时间
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;const int maxn = 200005;int n,m,a[maxn],dp[maxn][20];void init() // 从点i开始 长1<<j 的最大值{ for(int i = 1; i <= n; i++) dp[i][0] = a[i]; for(int j = 1; (1<<j) <= n; j++) for(int i = 1; i + (1<<j) - 1 <= n; i++) dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);}int rmq(int l,int r){int k = (int)(log(r - l + 1.0) / log(2.0));return max(dp[l][k],dp[r-(1<<k)+1][k]);}int solve(){ int prev = -1,sum,j,left,right; for(int i = 1; i <= n; i++)//段数 { int l = n / i; if(prev != l) { j = 1; sum = 0; } while(j <= i) { left = (j-1) * l + 1; right = j*l; sum += rmq(left,right); if(sum > m) return i; j++; } prev = l; } return -1;}int main(){while(scanf("%d%d",&n,&m),n != -1,m != -1){for(int i = 1; i <= n; i++)scanf("%d",&a[i]);init();printf("%d\n",solve());}return 0;}
0 0
- hdu 3486(RMQ+高效枚举)
- hdu 3486 rmq + 枚举
- hdu 5247(RMQ+枚举)
- hdu 5726 GCD RMQ+二分枚举
- hdu 3486(RMQ应用)
- hdu 3486 Interviewe 【RMQ】
- hdu 3486 RMQ + 二分
- hdu 3486 Interviewe (RMQ)
- HDU 3486 RMQ+二分
- HDU 3486 RMQ+二分
- hdu 5726 区间gcd RMQ+二分 || 暴力枚举
- hdu 3486 Interviewe 二分+RMQ
- hdu 3486 Interviewe(二分+rmq)
- hdu 3486 Interviewe(RMQ)
- HDU 3486 Interviewe(RMQ)
- HDU 3486 Interviewe(RMQ问题)
- HDU 3486 Interviewe(RMQ+二分)
- hdu 3486 Interviewe (二分+RMQ)
- Invalid Swift Support / invalid implementation of swift
- C++异常
- cmake使用整理
- Android APP安装后不在桌面显示图标的应用场景举例和实现方法
- 打造原生的图文混排控件
- hdu 3486(RMQ+高效枚举)
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分)
- 生成全排列
- HDU 1542-Atlantis(线段树+扫描线)
- BestCoder Round #66 GTW likes gt
- 共同学习Java源代码--数据结构--Collection接口
- HTML加入JavaScript
- 线程组
- [C/C++] main函数执行前后还会发生什么