「LOJ6039-珠宝 / Jewel Thief」题解

#6039. 「雅礼集训 2017 Day5」珠宝 /「NAIPC2016」Jewel Thief

sol

一类比较典的决策单调性吧,感觉对于余数的利用是很典的套路了。

直接背包显然是爆掉的,这里不作讲解。

不难发现,\(C\) 很小,考虑从 \(C\) 下手。

不难发现,同 \(C\) 的物品显然是 \(V\) 越大越优,因此同一个 \(C\) 选的越多得到的价值斜率单调递减,具有凸性。但对每个 \(C\) 背包显然还是爆掉的。

对于同一个 \(C\),不管选多少,新的占用空间对 \(C\) 余数不变。于是可以考虑对每个余数进行 DP。

还可以更快,不难发现 DP 转移显然是有决策单调性的,更小的空间如果决策点更大,由于上一层 DP 同样满足价值随空间不降,因此更大的空间显然决策点右移不劣,矛盾不合法。

分治处理一下即可。

code

const int N=1e6+5,K=5e4+5,C=305;

int n,k,m;
int c[N],w[N];
vec<ll> v[C];
ll f[2][K],g[2][K];
int d=0;

void solve(int l,int r,int pl,int pr,int i,int n){
    if(l>r)return;
    int m=l+r>>1,pm=0;g[d][m]=-INF;
    rep(p,max(pl,m-n),min(pr,m-1))if(g[d][m]<g[d^1][p]+v[i][m-p-1])g[d][m]=g[d^1][p]+v[i][m-p-1],pm=p;
    solve(l,m-1,pl,pm,i,n);solve(m+1,r,pm,pr,i,n);
}

inline void Main(){
    read(n,k);
    rep(i,1,n)read(c[i],w[i]),v[c[i]].pub(w[i]);
    rep(i,1,min(300,k)){
        d^=1;
        sort(v[i].begin(),v[i].end(),[](ll a,ll b){return a>b;});
        repl(j,1,v[i].size())v[i][j]+=v[i][j-1];
        rep(j,0,k)f[d][j]=f[d^1][j];
        repl(j,0,i){
            m=(k-j)/i;
            rep(l,0,m)g[d^1][l]=f[d^1][l*i+j];
            solve(0,m,0,m,i,v[i].size());
            rep(l,0,m)chmax(f[d][l*i+j],g[d][l]);
        }
    }
    rep(i,1,k)put(f[d][i],' ');
}
posted @ 2025-07-09 22:07  LastKismet  阅读(19)  评论(0)    收藏  举报