bzoj3163 - [Heoi2013]Eden的新背包问题

题目

https://www.lydsy.com/JudgeOnline/problem.php?id=3163

题解

做一个前缀背包,后缀背包,询问时候合并一下。。

话说预处理背包的部分用 log 拆分 跑得比单调队列还快好气呀。。。

#include <bits/stdc++.h>

using namespace std;

#define getchar getchar_unlocked

#define rep(i, n) for (int i = 0; i < n; ++i)

int get() {
  int n;
  char c;
  while ((c = getchar()) < '0');
  n = c - '0';
  while ((c = getchar()) >= '0') n = n * 10 + c - '0';
  return n;
}

int dpA[1010][1010], dpB[1010][1010];
int W[1010], V[1010], S[1010];
pair<int, int> deq[1010];

void solve() {
  int N;
  scanf("%d", &N);
  for (int i = 1; i <= N; ++i) {
    W[i] = get();
    V[i] = get();
    S[i] = get();
  }

  rep(i, N) {
    int* curr = dpA[i];
    int* next = dpA[i + 1];
    int w = W[i + 1], v = V[i + 1], s = S[i + 1];

    rep(q, w) {
      int b = (1000 - q) / w;
      int qh = 0, qt = 0;
      int ww = q - w, vv = -v;
      rep(j, b + 1) {
        ww += w;
        vv += v;
        int nd = curr[ww] - vv;
        while (qh != qt && nd >= deq[qt - 1].first) --qt;
        deq[qt++] = make_pair(nd, j);
        if (deq[qh].second == j - s - 1) ++qh;
        next[ww] = deq[qh].first + vv;
      }
    }
  }

  for (int i = N + 1; i >= 2; --i) {
    int* curr = dpB[i];
    int* next = dpB[i - 1];
    int w = W[i - 1], v = V[i - 1], s = S[i - 1];

    rep(q, w) {
      int b = (1000 - q) / w;
      int qh = 0, qt = 0;
      int ww = q - w, vv = -v;
      rep(j, b + 1) {
        ww += w;
        vv += v;
        int nd = curr[ww] - vv;
        while (qh != qt && nd >= deq[qt - 1].first) --qt;
        deq[qt++] = make_pair(nd, j);
        if (deq[qh].second == j - s - 1) ++qh;
        next[ww] = deq[qh].first + vv;
      }
    }
  }

  int Q;
  scanf("%d", &Q);
  rep(_, Q) {
    int id, w;
    scanf("%d %d", &id, &w);
    ++id;
    if (id == 1) {
      printf("%d\n", dpB[2][w]);
    } else if (id == N) {
      printf("%d\n", dpA[N - 1][w]);
    } else {
      int ma = 0;
      int* p = dpA[id - 1], *s = dpB[id + 1];
      for (int j = 0; j <= w; ++j) {
        ma = max(ma, p[j] + s[w - j]);
      }
      printf("%d\n", ma);
    }
  }
}

int main() {
  solve();
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/arg-53/p/9050315.html