[BZOJ] 3163: [Heoi2013]Eden的新背包问题

这个复杂度不能接受,但是确实能过。

二进制拆分多重背包可过,做的时候记录前缀后缀和,就是不优化背包的第一维。

nlogn件物品,预处理复杂度O(nmlogn),看起来还行

每次询问暴力合并,O(qm),3*10^8,看起来有点难受。

#include<iostream>
#include<cstdio>

using namespace std;

inline int rd(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}

const int MAXN=1024<<3;

int a[MAXN],val[MAXN],tot;

int f[MAXN][1024],g[MAXN][1024];

int n,m;

int pos[MAXN];

int main(){
    n=rd();
    int x,y,z;
    for(int i=1;i<=n;i++){
        x=rd();y=rd();z=rd();
        for(int j=0;(1<<j)<=z;j++){
            z-=(1<<j);a[++tot]=x*(1<<j);val[tot]=y*(1<<j);
        }
        if(z){a[++tot]=x*z;val[tot]=y*z;}
        pos[i]=tot;
    }
    for(int i=1;i<=tot;i++){
        for(int j=1000;j>=0;j--){
            f[i][j]=f[i-1][j];
            if(j>=a[i])f[i][j]=max(f[i-1][j],f[i-1][j-a[i]]+val[i]);
        }
    }
    for(int i=tot;i>=1;i--){
        for(int j=1000;j>=0;j--){
            g[i][j]=g[i+1][j];
            if(j>=a[i])g[i][j]=max(g[i+1][j],g[i+1][j-a[i]]+val[i]);
        } 
    }
    m=rd();
    int ans=0;
    for(int i=1;i<=m;i++){
        x=rd()+1;y=rd();ans=0;
        for(int j=0;j<=y;j++){
            ans=max(f[pos[x-1]][j]+g[pos[x]+1][y-j],ans);
        }
        printf("%d
",ans);
    }
    return 0;
}
未经许可,禁止搬运。
原文地址:https://www.cnblogs.com/ghostcai/p/9507562.html