这个复杂度不能接受,但是确实能过。
二进制拆分多重背包可过,做的时候记录前缀后缀和,就是不优化背包的第一维。
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; }