RT,大致思路就是二进制优化+正反跑两遍背包然后再排除限制物品后统计答案,结果只有55分QAQ
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define int long long
int n,m,q,ans=-1,cnt,maxn=-1;
int li[1001000],mm[1001000];
int f1[100002][1002],f2[100002][1002];
struct node{
int id,cos,w;
}num[500100];
signed main()
{
scanf("%lld",&n);
for(int i=1;i<=n;++i)
{
int a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
int bas=1;
while(c)
{
++cnt;
if(c>=bas)
{
c-=bas;
num[cnt].id=i;
num[cnt].cos=a*bas;
num[cnt].w=b*bas;
}
else
{
num[cnt].id=i;
num[cnt].cos=a*c;
num[cnt].w=b*c;
c=0;
}
bas*=2;
}
}
scanf("%lld",&q);
for(int i=1;i<=q;++i)
{
scanf("%lld%lld",&li[i],&mm[i]);
maxn=max(maxn,mm[i]);
}
for(int i=1;i<=cnt;++i)
{
for(register int j=0;j<=maxn;++j)f1[i][j]=f1[i-1][j];
for(register int j=maxn;j>=num[i].cos;--j)
f1[i][j]=max(f1[i][j],f1[i-1][j-num[i].cos]+num[i].w);
}
for(int i=cnt;i>=1;--i)
{
for(register int j=0;j<=maxn;++j)f2[i][j]=f2[i+1][j];
for(register int j=maxn;j>=num[i].cos;--j)
f2[i][j]=max(f2[i][j],f2[i+1][j-num[i].cos]+num[i].w);
}
for(int i=1;i<=q;++i)
{
int l=0,r=0,cur=li[i]+1;m=mm[i];
while(num[l+1].id<cur&&l<n)++l;
r=l;
while(num[r+1].id<=cur&&r<n)++r;
ans=-1;
for(register int j=0;j<=m;++j)
ans=max(ans,f1[l][j]+f2[r+1][m-j]);
printf("%lld\n",ans);
}
return 0;
}