P1776 宝物筛选_NOI导刊2010提高(02)
https://www.luogu.org/problemnew/show/P1776
模版的多重背包,但朴素肯定不行,这里采用单调队列优化
朴素方程式
变形
(第一维压掉)
如此,便可以用分mod用单调队列优化啦,代码如下
1 #include <bits/stdc++.h> 2 #define up(i,l,r) for(register int i = (l); i <= (r); ++i) 3 #define dn(i,l,r) for(register int i = (l); i >= (r); --i) 4 #define ll long long 5 #define re register 6 #define _N putchar('\n') 7 using namespace std; 8 9 template <typename T> void in(T &x) { 10 x = 0; T f = 1; char ch = getchar(); 11 while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} 12 while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();} 13 x *= f; 14 } 15 16 template <typename T> void out(T x) { 17 if(x < 0) x = -x , putchar('-'); 18 if(x > 9) out(x/10); 19 putchar(x%10 + 48); 20 } 21 //--------------------------------------------------------------- 22 23 const int N = 40007; 24 25 int n,max_w,tmp,ans,f[N],num[N]; 26 27 struct { 28 int pos,v; 29 }que[N]; 30 31 int main() { 32 freopen("0.in","r",stdin); 33 in(n); in(max_w);int v,w,cnt; 34 for(int i = 1; i <= n; ++i) { 35 in(v); in(w); in(cnt); 36 if(!w) { 37 tmp += cnt * v; continue; 38 } 39 int a = min(cnt,max_w/w); 40 for(int mod = 0; mod < w; ++mod) { 41 int head = 0,tail = 0,c = (max_w-mod)/w; 42 for(int k = 0; k <= c; ++k) { 43 int add = f[k*w+mod] - k*v; 44 while(head < tail && add >= que[tail-1].v) --tail; 45 ++tail; que[tail-1].v = add,que[tail-1].pos = k; 46 47 while(head < tail && que[head].pos + a < k) ++head; 48 49 f[k*w+mod] = max(f[k*w+mod],que[head].v + k*v);// 50 ans = max(ans,f[k*w+mod]); 51 } 52 } 53 } 54 out(ans+tmp); 55 return 0; 56 }