洛谷 P3537 [POI2012]SZA-Cloakroom 解题报告
洛谷 P3537 [POI2012]SZA-Cloakroom 解题报告
题意
有\(n\)件物品,每件物品有三个属性\(a[i], b[i], c[i] (a[i]<b[i])\)。
再给出\(q\)个询问,每个询问由非负整数\(m, k, s\)组成,问是否能够选出某些物品使得:
- 对于每个选的物品i,满足\(a[i]<=m且b[i]>m+s\)。
- 所有选出物品的\(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
本文来自博客园,作者:zjsqwq,转载请注明原文链接:https://www.cnblogs.com/zjsqwq/p/16356759.html

浙公网安备 33010602011771号