题解:P11912 [PA 2025] 集合 2 / Zbiory 2
Skeleton_Huo · · 题解
前言
基本承袭 gcx12012 大佬的思路,但删除部分显然有更简洁的做法。另外代码并不会多一次操作。
Solution
我们考虑维护当前构造的集合
枚举
- 若
i \in S 且i \notin T ,我们需要把i 从S 中删去,即S \leftarrow S \backslash A_i ,因为A \backslash B = A \cap \overline{B} ,所以我们,只要求一个A_i 的补集,再与S 求交集即可。 - 若
i \notin S 且i \in T ,直接S \leftarrow S \cup A_i 。
至多
可以任意你喜欢的数据结构(比如数组)维护 “本题非同寻常的时空限制”是何意味)。
Code
#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define _rep(i, l, r) for (int i = (l); i >= (r); i--)
using namespace std;
constexpr int N = 5e4 + 10;
struct Operation {
int op, x, y;
Operation(int op, int x, int y) : op(op), x(x), y(y) {}
};
vector<Operation> ans;
bitset<N> s, t;
signed main() {
int n, k;
cin >> n >> k;
rep(i, 1, k) {
int b;
cin >> b;
t[b] = 1;
}
int idx = n;
s[n] = 1;
rep(i, 1, n) {
if (s[i] && !t[i]) {
ans.emplace_back(3, i, 0);
ans.emplace_back(2, idx, idx + 1);
idx += 2;
for (int j = i; j <= n; j += i)
s[j] = 0;
} else if (!s[i] && t[i]) {
ans.emplace_back(1, idx, i);
idx++;
for (int j = i; j <= n; j += i)
s[j] = 1;
}
}
cout << ans.size() << "\n";
for (auto v : ans) {
if (v.op == 3)
cout << v.op << " " << v.x << "\n";
else
cout << v.op << " " << v.x << " " << v.y << "\n";
}
return 0;
}
后记
并不认为这道题很简单,感觉方向容易找错,比如本人刚开始一直考虑构造出单元素集合再求并,但那样顶多做到