点击查看代码
#include <bits/stdc++.h>
#define lowbit(x)(x&(-x))
using namespace std;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
#define int long long
#define ld long double
#define __ cout<<"!"<<"\n"
#define ___ cout<<"?"<<"\n"
#define ____ cout<<"$"<<"\n"
#define _____ cout<<"@"<<"\n"
#define ls(x) tree[x].ls
#define rs(x) tree[x].rs
#define val(x) tree[x].val
#define mark(x) tree[x].mark
typedef pair<int,int> pairint;
const int MAXN=1e5+9;
const int N=1e5+9;
const int INF=(1e15);
const int mod=1e9+7;
/*char *p1,*p2,budp[100000];
int read()
{
int x=0,f=1;char ch=nc();
while(ch<48||ch>57){if(ch=='-')f=-1;ch=nc();}
while(ch>=48&&ch<=57)x=x*10+ch-48,ch=nc();
return x*f;
}*/
int n,W;
int dp[MAXN];
struct NODE
{
int pos,value;
}que[MAXN];
int c[MAXN],w[MAXN],num[MAXN];
void solve()
{
cin>>n>>W;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;++i)//枚举物品种类
{
cin>>w[i]>>c[i]>>num[i];//c,w,num分别对应 体积,价值,个数
if(W/c[i] <num[i]) num[i]=W/c[i];//求lim
for(int mo=0;mo<c[i];mo++)//枚举余数
{
int head=0,tail=0;//队列初始化
for(int k=0;k<=(W-mo)/c[i];k++)
{
int x=k;
int y=dp[k*c[i]+mo]-k*w[i];
while(head<tail && que[head].pos<k-num[i])head++;//限制长度
while(head<tail && que[tail-1].value<=y)tail--;
que[tail].value=y,que[tail].pos=x;
tail++;
dp[k*c[i]+mo]=que[head].value+k*w[i];
//加上k*w[i]的原因:
//我们的单调队列维护的是前i-1种的状态最大值.
//因此这里加上k*w[i].
//cout<<dp[k*c[i]+mo]<<"\n";
}
}
}
cout<<dp[W]<<"\n";
return;
}
signed main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t=1;//cin>>t;
while(t--){
solve();
}
return 0;
}