hdu 2430 Beans

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

题解:

1.目标是求(sum[i] - sum[j](i != j)) % p <= k && 使得sum[i] - sum[j]最大

2.变形-----(sum[i] % p - sum[j] % p + p) % p <= k

3.然后我们可以按sum[i] % p,给数组排序。

4.用单调队列分情况讨论解决这个问题了

5.hint:因为存在某堆有0个bean的情况,需要在排序的时候特殊处理

总结:

1.这道题又是看到zeroclock说需要把式子变形之后才知道怎么写的。

2.当没有方向的时候,应该尝试着对公式进行小小的变形,貌似在这种地方栽过好几次跟头了

3.最近依旧学习opencv,几乎把书从头到尾的读了一遍,发现确实应该抓住重点看书,看急需了解的知识,对于不会

需要延伸的知识,再去有目的的查资料,这样效率更高!

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
#define MAXN 1000005
int n,p,k;
struct Node
{
    ll s;
    bool operator < (const Node & a)const{
        if(s % p == a.s % p)return s < a.s;
        return s % p < a.s % p;
    }
}node[MAXN];
ll deque[MAXN];
int main()
{
    int _;
    for(int kcas = scanf("%d",&_);kcas <= _;kcas++)
    {
        scanf("%d%d%d",&n,&p,&k);
        bool success = false;
        for(int i = 1;i <= n;i++)
        {
            scanf("%I64d",&node[i].s);
            if(node[i].s == 0)success = true;
            node[i].s += node[i - 1].s;
        }
        sort(node,node + n + 1);
        ll maxn = 0,ans = 0;
        int tail = 0,head = 0;
        for(int i = 1,j = 0;i <= n;i++)
        {
            while(tail != head && deque[tail - 1] > node[i - 1].s)
                tail--;
            deque[tail++] = node[i - 1].s;
            while(tail != head && deque[head] % p + k < node[i].s % p)
                head++;
            if(head != tail)ans = max(ans,node[i].s - deque[head]);

            while(j < i && node[j].s % p + p - node[i].s % p <= k)
            {
                maxn = max(maxn,node[j].s);
                j++;
            }
            ans = max(ans,maxn - node[i].s);
        }
        if(!ans && !success)printf("Case %d: -1\n",kcas);
        else printf("Case %d: %I64d\n",kcas,ans / p);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值