单调队列优化多重背包

某次模拟赛,考到了背包问题,但是因为复杂度分析后发现极限数据用普通背包方法过不去,但是实际上数据水了,这种方法就过了,我又没敢写。。。我也很绝望啊。。。
如果当时会写单调队列优化多重背包就没这么多事了。。。

链接:https://www.cnblogs.com/JoeFan/p/4165956.html
题目:[HEOI2013]Eden 的新背包问题

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1005;
int n,a[N],b[N],c[N],q1[N<<2],q2[N<<2],h1,h2,t1,t2,cnt,f[N][N],g[N][N];
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]);
    for(int i=1,tp;i<=n;i++) {
        for(int v=0;v<a[i];v++) {
            cnt=h1=t1=h2=t2=0;
            for(int k=v;k<=1000;k+=a[i]){
                if(t1-h1==c[i]+1) {
                    if(q1[h1+1]==q2[h2+1]) h2++;
                    h1++;
                }
                tp=f[i-1][k]-cnt*b[i];
                q1[++t1]=tp;
                while(h2<t2&&q2[t2]<tp) t2--;
                q2[++t2]=tp;
                f[i][k]=q2[h2+1]+cnt*b[i];
                cnt++;
            }
        }
    }
    for(int i=n,tp;i;i--) {
        for(int v=0;v<a[i];v++) {
            cnt=h1=t1=h2=t2=0;
            for(int k=v;k<=1000;k+=a[i]){
                if(t1-h1==c[i]+1) {
                    if(q1[h1+1]==q2[h2+1]) h2++;
                    h1++;
                }
                tp=g[i+1][k]-cnt*b[i];
                q1[++t1]=tp;
                while(h2<t2&&q2[t2]<tp) t2--;
                q2[++t2]=tp;
                g[i][k]=q2[h2+1]+cnt*b[i];
                cnt++;
            }
        }
    }
    int q;
    scanf("%d",&q);
    int d,e,ans=0;
    while(q--) {ans=0;
        scanf("%d%d",&d,&e);d++;
        for(int i=0;i<=e;i++) ans=max(ans,f[d-1][i]+g[d+1][e-i]);
        printf("%d\n",ans);
    }
}
posted @ 2018-08-20 11:06  SWHsz  阅读(289)  评论(0编辑  收藏  举报