bzoj3163 Eden的新背包问题

多重背包,$q$ 次询问,每次问删一个物品之后花费 $x$ 能装多少物品

$n \leq 3000, x \leq 1000, q \leq 300000$

sol:

网上有很多假做法

正解应该是考虑分治

先二进制拆物品,然后记 $solve(l,r)$ 表示不考虑 $[l,r]$ 的操作的 dp

每次递归的时候先把 $[mid+1,r]$ 的 dp 数组搞出来,然后递归 $[l,mid]$,然后删除 $[mid+1,r]$

同样的,把 $[l,mid]$ 的 dp 数组搞出来,递归 $[mid+1,r]$ ,然后删除 $[l,mid]$

这样每层实际上只跑了一次 dp,分治有 log 层,所以复杂度是 $O(n^2log^2n)$ (拆物品带一个 log,重量与 $n$ 同级)

单调队列可以少一个 log

#include<bits/stdc++.h>
#define LL long long
#define rep(i,s,t) for(register int i = (s),i##end = (t); i <= i##end; ++i)
#define dwn(i,s,t) for(register int i = (s),i##end = (t); i >= i##end; --i)
using namespace std;
inline int read()
{
    int x=0,f=1;char ch;
    for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
    for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
    return x*f;
}
const int maxn = 50010;
vector<pair<int, int> > qs[maxn];
int n, dfn, curdep;
int a[maxn], b[maxn], lb[maxn], rb[maxn];
int ans[10 * maxn], dp[1010], fzd;
void cdq(int l, int r) {
    if(l == r) {
        rep(i, 0, qs[l].size() - 1) ans[qs[l][i].second] = dp[qs[l][i].first];
        return;
    }
    int mid = (l + r) >> 1;
    int tmp[1010];
    memcpy(tmp, dp, sizeof(tmp)); //fzd++;
    rep(i, lb[mid+1], rb[r]) dwn(j, 1000, a[i]) dp[j] = max(dp[j], dp[j - a[i]] + b[i]);
    cdq(l, mid);
    memcpy(dp, tmp, sizeof(dp)); //fzd++;
    rep(i, lb[l], rb[mid]) dwn(j, 1000, a[i]) dp[j] = max(dp[j], dp[j - a[i]] + b[i]);
    cdq(mid+1, r);
    memcpy(dp, tmp, sizeof(dp)); //fzd++;
}
int main()
{
    n = read();
    rep(i, 1, n) {
        int u = read(), v = read(), w = read(), j;
        lb[i] = dfn + 1;
        for(j=1;(j<<1)<=(w+1);j<<=1)  dfn++, a[dfn] = u * j, b[dfn] = v * j;
        if(w+1-j>0) dfn++, a[dfn] = (w+1-j) * u, b[dfn] = (w+1-j) * v;
        rb[i] = dfn;
    }
    int q = read();
    rep(i, 1, q) {
        int x = read() + 1, y = read();
        qs[x].push_back(make_pair(y, i));
    }
    cdq(1, n);
    rep(i, 1, q) printf("%d\n", ans[i]);
    //if(fzd >= 3 * n) cout << "False" << endl;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Kong-Ruo/p/10562205.html