题意:有n堆豆子,选择其中连续的几堆,装进大小为m的袋子中,问最多能装满几袋,在剩余豆子不超过k的情况下。
思路:求(sum[i] - sum[j](i != j)) % m <= k && 使得(sum[i] - sum[j])/m最大。可以按sum[i] % m,给数组排序,用单调队列来解决这个问题。用余数的差距去维护是否出队列。维护队列递增sum[i](头小尾大)。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 25
int top;
struct code
{
int sum,yu;
} edge[1000006];
bool cmp(code a,code b)
{
if(a.yu!=b.yu)
return a.yu<b.yu;
else
return a.sum<b.sum;
}
int main()
{
int n,m,k;
int t,x;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
edge[0].sum=0;
edge[0].yu=0;
for(int i=1; i<=n; i++)
{
scanf("%d",&x);
edge[i].sum=edge[i-1].sum+x;
edge[i].yu=edge[i].sum%m;
}
sort(edge,edge+n+1,cmp);
deque<int>p;
int ans=-1;
for(int i=0; i<=n; i++)
{
if(!p.empty()&&edge[i].sum<edge[p.back()].sum)
p.pop_back();
p.push_back(i);
while(!p.empty()&&edge[p.back()].yu-edge[p.front()].yu>k)
{
p.pop_front();
}
if(p.size()>1)
{
ans=max(ans,(edge[p.back()].sum-edge[p.front()].sum)/m);
}
}
printf("Case %d: %d\n",++top,ans);
}
return 0;
}