hdu 2430 Beans

来源:互联网 发布:php setlocale 中文 编辑:程序博客网 时间:2024/05/16 16:01

题意:题目大意:有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 1000005int 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