题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2430

题目大意:有n坨豌豆,每坨都有w[i]个,现在要从中选择连续的若干坨,然后用一个能装p个豌豆的背包装豆子,直到剩下的豌豆数量<=p为止,还要求剩下的豌豆数量少于k,问最多能装多少包。

解题思路:题意很明了,模型也很好抽象。本题就是要选择连续的一段和为sum,使得max(sum/p) 且sum%p<=k。那么要怎么算这个sum呢?这里就大有文章可做了。

其实这类求区间和的问题很经常是用sum[i]- sum[j-1]这种方式来表达的,我们设sum[i]表示0到i坨豌豆的总数量,那么上面的sum就是sum[i]-sum[j-1]。从而得到一个式子,max(sum[i]-sum[j]) (j < i && (sum[i]-sum[j])%p<=k),表示以i为区间尾,因为豌豆数量非负数,那我们向前找个最小的下标使得差最小且符合条件即可。

我们设sum[i]为x,sum[j]为y,那么上式变成0<=(x-y)%p<=k且x-y最大,约束条件是x大等于y,我们要利用这些条件快速地找到x对应的那个最小的y。

0<=(x-y)%p<=k  -->  0<=(x%p - y%p + p) % p<=k

如果x%p >= y%p,那么x%p-k<=y%p<=x%p,我们就可以根据x%p来定位y%p.

如果x%p < y%p,那么我们可以换个角度想,在以y结尾的时候就会有上面的情况。

那问题就剩下一个了,如果根据x%p来快速定位y%p。写法有多种,用线段树和树状数组都可以写,但我用线性的单调队列来写,时间78ms,是提交记录的第二名。

我先将每个和对p取余得到一个余数r数组,然后按余数大小优先位置其次的顺序排序。排完序之后就可以根据ri - k <= rj <= ri来往前找那个最小的j。遍历数组r,因为r是有序的,我用单调队列储存r小于当前的最小下标。关于单调队列,我就不多说了,百度google去。最后更新答案即可。

总复杂度还是(nlogn),主要用于排序。

测试数据:

20
2 19 3
17 3
Out:Case 1: 1

2 19 1

17 3
Out:Case 2: 1

2 19 3

17 6
Out:Case 3: -1

10 20 10

0 3 1 8 19 39 2 9 1 8

Out:Case 4: 4

3 100 10

32 34 23
Out:Case 5: -1

1 5 3

5
Out:Case 6: 1

5 15 4

7 8 3 10 10
Out:Case 7: 2

C艹代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define MAX 1000010
#define max(a,b) (a)>(b)?(a):(b)struct node {int x,in;
}r[MAX],qu[MAX];
__int64 sum[MAX],ans;
int head,tail;
int n,p,k,mmin[MAX];int cmp(node a,node b) {if (a.x == b.x) return a.in < b.in;else return a.x < b.x;
}
void Solve_AC() {int i,j;head = 0,tail = 1;for (i = 1; i <= n; ++i) {if (tail > head) mmin[r[i].in] = -1;else mmin[r[i].in] = qu[tail].in;while (tail <= head && r[i].in < qu[head].in)  head--;qu[++head] = r[i];while (tail <= head && r[i + 1].x - qu[tail].x > k)tail++;}for (i = 1; i <= n; ++i) {if (sum[i] % p <= k) ans = max(ans,sum[i] / p);if (mmin[i] == -1 || mmin[i] >= i) continue;ans = max(ans,(sum[i] - sum[mmin[i]]) / p);}
}int main()
{int i,j,t,cas = 0;scanf("%d",&t);while (t--) {scanf("%d%d%d",&n,&p,&k);for (i = 1; i <= n; ++i) {scanf("%d",&sum[i]);r[i].in = i;sum[i] +=  sum[i-1];r[i].x = sum[i] % p;}sort(r+1,r+1+n,cmp);ans = -1,Solve_AC();printf("Case %d: %I64d\n",++cas,ans);}
}

本文ZeroClock原创,但可以转载,因为我们是兄弟。

Hdu 2430 Beans (数据结构_单调队列)相关推荐

  1. Hdu 4193 Non-negative Partial Sums (数据结构_单调队列)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4193 题目大意: 给定一个长度为n的循环序列,从n个不同位置开始,问有几个位置使得一下情况成立:所有 ...

  2. BZOJ_2343_[Usaco2011 Open]修剪草坪 _单调队列_DP

    BZOJ_2343_[Usaco2011 Open]修剪草坪 _单调队列_DP 题意: N头牛,每头牛有一个权值,选择一些牛,要求连续的不能超过k个,求选择牛的权值和最大值 分析: 先考虑暴力DP,f ...

  3. HDU 5945 Fxx and game 单调队列优化dp

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5945 题目 Young theoretical computer scientist Fxx desi ...

  4. 蒟蒻的ACM数据结构(四)-单调队列和单调栈

    单调队列和单调栈 一.概念 二.实现 三.题目 单调队列 洛谷P1886 滑动窗口 解析 单调栈 [GXOI/GZOI2019]与或和 解析 POJ3250 Bad Hair Day 解析 POJ 2 ...

  5. HDU 3507 Print Article(单调队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3507 题意:给出一个数列C,一个数字M,将数列分成若干段,每段的代价为(设这段的数字为k个): 求一种 ...

  6. 【单调队列】数据结构之单调队列详解

    博客主页: https://blog.csdn.net/qq_50285142 欢迎点赞

  7. hdu 3401(单调队列优化dp)

    注意:这题题意是有操作的天数相隔要大于w 然后列出状态转移方程就可以发现,可以用优点队列优化啦. 构造状态dp[i][j]表示第i 天拥有 j只股票的时候,赚了多少钱 状态转移有: 1.从前一天不买不 ...

  8. bzoj1233 单调队列优化dp

    https://www.lydsy.com/JudgeOnline/problem.php?id=1233 数据结构优化dp的代码总是那么抽象 题意:奶牛们讨厌黑暗. 为了调整牛棚顶的电灯的亮度,Be ...

  9. 多重背包单调队列优化思路_动态规划入门——多重背包与单调优化

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法与数据结构的第14篇文章,也是动态规划专题的第三篇. 在之前的文章当中,我们介绍了多重背包的二进制拆分的解法.在大多数情况下,这种 ...

最新文章

  1. 单元和集成测试的代码覆盖率
  2. HttpServletRequestWrapper使用技巧(自定义session和缓存InputStream)
  3. 关于神经网络的调参经验技巧和调参顺序
  4. CPC系统在win10上的安装,1小时快速安装
  5. VCPKG 升级问题
  6. USB加密狗复制克隆破解软件
  7. 公司人事管理系统(C++)
  8. python 双重差分模型_计量经济学导论13:虚拟变量与双重差分
  9. c语言字符大于等于怎么打,c语言大于等于怎么打?
  10. 电力系统潮流程序C语言,电力系统潮流C语音程
  11. IPA第八届少儿模特明星盛典 福州赛区 初赛圆满收官
  12. 爬取起点小说+mongoDB存储
  13. Mac上的EditPlus-BBEdit快捷键大全
  14. 帝国 ajax评论插件,最简单实用的帝国cms评论插件
  15. 打开谷歌浏览器提示输入密钥环
  16. 【MIT算法导论】哈希表、全域哈希
  17. 基于Matlab Robotics Toolbox的Dobot机械臂运动规划(2)
  18. python中update是啥意思_python中update的基本使用
  19. 关于upp和lower
  20. 凡事就怕认真:强迫症米粉24Hr电池优化实测

热门文章

  1. 机器人工程终身学习和工作计划-2022-
  2. Random类中的nextInt()函数
  3. TextView 多行文字末尾添加图片
  4. nfs 客户端卡死问题
  5. 电脑系统重装步骤教程,一键重装win7系统方法
  6. Ubuntu ee key too small
  7. java微信开发教程
  8. wpf绘制圆环,实现图片镂空
  9. Apache OpenSSL生成CA证书使用
  10. Java项目:医药信息管理系统(java+SSM+HTML+easyui+mysql)