洛谷 P3537 [POI2012]SZA-Cloakroom 解题报告

洛谷 P3537 [POI2012]SZA-Cloakroom 解题报告

link

题意

\(n\)件物品,每件物品有三个属性\(a[i], b[i], c[i] (a[i]<b[i])\)

再给出\(q\)个询问,每个询问由非负整数\(m, k, s\)组成,问是否能够选出某些物品使得:

  1. 对于每个选的物品i,满足\(a[i]<=m且b[i]>m+s\)
  2. 所有选出物品的\(c[i]\)的和正好是\(k\)

Solutions

考虑将所有物品和询问都 离线排序 ,将\(q\)次背包转化为\(1\)次背包。

按照\(m\)升序排序询问,按照\(a\)升序排序物品。

\(a_i \le m\)为条件依次遍历插入物品,记\(f_k\)表示某集合的\(\sum_{i=1}^n c_i\)等于\(k\)时,集合中元素的\(b_i\)最小值的最大化值。

即让\(b_i\)最小值尽可能大。

剩余步骤按照01背包来即可。

依次遍历每个询问,同时对应遍历符合条件的物品集合,时间复杂度\(O(nq)\)

Details

对于物品属性的输入顺序是\(c_i, a_i, b_i\), 而翻译中并未说明。

Code

#include <bits/stdc++.h>
using namespace std;
inline int read() {
    int x = 0; char ch = getchar(); bool sgn = 0;
    while (ch < '0' || ch > '9') sgn |= ch == '-', ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + (ch & 15), ch = getchar();
    return sgn ? -x : x;
}
const int MN = 1e6 + 10, INF = 0x7fffffff;
int n, q;
struct Objects {
    int a, b, c;
    bool operator < (const Objects &x) const {
        return a < x.a;
    }
} a[MN];
struct Asks {
    int m, k, s, pos;
    bool operator < (const Asks &x) const {
        return m < x.m;
    }
} b[MN];
int dp[MN];
bool ans[MN];
signed main() {
    n = read();
    for (int i = 1; i <= n; ++i) a[i].c = read(), a[i].a = read(), a[i].b = read();
    sort(a + 1, a + 1 + n);
    q = read();
    for (int i = 1; i <= q; ++i) b[i].m = read(), b[i].k = read(), b[i].s = read(), b[i].pos = i;
    sort(b + 1, b + 1 + q);
    dp[0] = INF;
    for (int i = 1, j = 1; i <= q; ++i) {
        while (j <= n && a[j].a <= b[i].m) {
            for (int k = 100000; k >= a[j].c; --k) dp[k] = max(dp[k], min(dp[k - a[j].c], a[j].b));
            j++;
        }
        if (dp[b[i].k] > b[i].m + b[i].s) ans[b[i].pos] = true;
    }
    for (int i = 1; i <= q; ++i) cout << (ans[i] ? "TAK" : "NIE") << '\n';
    return 0;
}

Data

言简意赅の思路:https://www.luogu.com.cn/blog/MloVtry/solution-p3537

《翻译有误》社死现场https://www.luogu.com.cn/discuss/446210

posted @ 2022-06-08 18:34  zjsqwq  阅读(45)  评论(0)    收藏  举报