题意:给你一些物品的价值,代价和个数,有q次询问,每次给你一个新的价钱而且规定其中一种物品不能使用,问你每次的最大价值。。
一看见q的范围就想歪了,q<=10^5我就以为是不是要搞什么数据结构,因为以前好像看过这种姿势。。
结果被打脸了,又被教导了一波新姿势。。直接跑两遍完全背包,正反各一遍,然后跑的时候用前缀和来dp。。那最后的时候询问就能q*m解决。。也就是1e8,潜意识觉得不能过。。然而过了,而且飞快。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
int n,m;
const int N=1e3+5;
typedef long long ll;
int cost[N],val[N],lim[N];
int f[N][N],g[N][N],h[N][N];
int main()
{
scanf("%d",&n);
fo(i,1,n)
scanf("%d%d%d",&cost[i],&val[i],&lim[i]);
fo(i,1,n)
{
int tmp=lim[i];
fo(j,0,1000)f[i][j]=f[i-1][j];
for(int j=1;tmp;j=min(j<<1,tmp))
{
for(int k=1000;k>=j*cost[i];k--)
f[i][k]=max(f[i][k],f[i][k-j*cost[i]]+j*val[i]);
tmp-=j;
}
}
fd(i,n,1)
{
int tmp=lim[i];
fo(j,0,1000)g[i][j]=g[i+1][j];
for(int j=1;tmp;j=min(j<<1,tmp))
{
for(int k=1000;k>=j*cost[i];k--)
g[i][k]=max(g[i][k],g[i][k-j*cost[i]]+j*val[i]);
tmp-=j;
}
}
int q;
scanf("%d",&q);
fo(i,1,q)
{
int x,y;
scanf("%d%d",&x,&y);
++x;
int ans=0;
fo(j,0,y)
ans=max(ans,f[x-1][j]+g[x+1][y-j]);
printf("%d\n",ans);
}
return 0;
}