单调队列 1005 HDU 2430 Beans

来源:互联网 发布:网络统考时间 编辑:程序博客网 时间:2024/05/19 02:30

题意:
有n袋大豆,每袋大豆里有w[i]个大豆,现在有容量为p的包
问你选任意长度的连续区间,这个区间满足Sum%p<=k|Sum是区间的和
答案使Sum/p最大
思路:
区间嘛,很容易想到前缀和来表示区间和
区间(j+1)~i就是Sum[i]-Sum[j](为了使Sum[j]好表示些,所以前边用了j+1
判断此区间%p是否小于<=k
(Sum[i]-Sum[j])%p==(Sum[i]%p-Sum[j]%p+p)%p
如果Sum[i]%p>=Sum[j]%p,这个我们下面讨论
如果Sum[i]%p

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<math.h>#include<queue>#include<stack>#include<string>#include<vector>#include<map>#include<set>using namespace std;#define lowbit(x) (x&(-x))typedef long long LL;const int maxn = 1000005;const int inf=(1<<28)-1;int w[maxn],Min[maxn];LL Sum[maxn];struct node{    int pos;    LL x;}Mod[maxn];bool cmp(node u,node v){    if(u.x==v.x) return u.pos<v.pos;    return u.x<v.x;}int main(){    int T,Case=0;    scanf("%d",&T);    while(T--)    {        int n,p,k;        scanf("%d%d%d",&n,&p,&k);        for(int i=1;i<=n;++i)        {            scanf("%d",&w[i]);            Mod[i].pos=i;            Sum[i]=Sum[i-1]+w[i];            Mod[i].x=Sum[i]%p;        }        sort(Mod+1,Mod+n+1,cmp);        deque<node>Que;        LL Ans=-1;        for(int i=1;i<=n;++i)        {            while(!Que.empty()&&Que.back().pos>Mod[i].pos)            Que.pop_back();            while(!Que.empty()&&Mod[i].x-Que.front().x>k)            Que.pop_front();            if(Mod[i].x<=k) Ans=max(Ans,Sum[Mod[i].pos]/p);            if(!Que.empty()) Ans=max(Ans,(Sum[Mod[i].pos]-Sum[Que.front().pos])/p);            Que.push_back(Mod[i]);        }        printf("Case %d: %lld\n",++Case,Ans);    }    return 0;}
0 0
原创粉丝点击