#決策單調性dp,分治#LOJ 6039「雅禮集訓 2017 Day5」珠寶
阿新 • • 發佈:2022-03-23
分析
觀察到這個0/1揹包中單個物品的體積不超過300,考慮分體積考慮。
設 \(dp[i]\) 表示容量大小為 \(i\) 的揹包能獲得的最大價值,
\(dp[i]=\max\{dp[i-j]+s[j]\}\) 是滿足四邊形不等式的,好像和凸性有關。
所以直接用決策單調性實現,列舉餘數,就可以做到 \(O(m \max\{a_i\}\log m)\)
程式碼
#include <cstdio> #include <cctype> #include <functional> #include <algorithm> using namespace std; const int N=50011; struct node{int y,next;}e[N*20]; typedef long long lll; int T,tot,n,m,mx,as[N]; lll dp[N],f[N],s[N*20],g[N]; int iut(){ int ans=0; char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=ans*10+c-48,c=getchar(); return ans; } void print(lll ans){ if (ans>9) print(ans/10); putchar(ans%10+48); } void Max(lll &x,lll y){x=x>y?x:y;} int max(int a,int b){return a>b?a:b;} void dfs(int l,int r,int L,int R){ if (l>r) return; int mid=(l+r)>>1,MID=L; lll ans=0; for (int j=max(mid-n,L);j<=mid&&j<=R;++j) if (g[j]+s[mid-j]>ans) ans=g[j]+s[mid-j],MID=j; Max(f[mid],ans); dfs(l,mid-1,L,MID); dfs(mid+1,r,MID,R); } int main(){ T=iut(),m=iut(); for (int i=1;i<=T;++i){ int x=iut(),y=iut(); mx=max(mx,x); e[i]=(node){y,as[x]},as[x]=i; } for (int i=1;i<=mx;++i) if (as[i]){ n=0; for (int j=as[i];j;j=e[j].next) s[++n]=e[j].y; sort(s+1,s+1+n,greater<int>()); for (int j=1;j<=n;++j) s[j]+=s[j-1]; for (int j=0;j<i;++j){ tot=0; for (int k=j;k<=m;k+=i) g[++tot]=dp[k],f[tot]=0; dfs(1,tot,1,tot); tot=0; for (int k=j;k<=m;k+=i) Max(dp[k],f[++tot]); } } for (int i=1;i<=m;++i) print(dp[i]),putchar(32); return 0; }