题解:P4934 礼物
Mrkn_chenyx12 · · 题解
解题思路
首先我们可以发现,假设
考虑拓扑排序,每个数字
但是这样每个数字连出边的量级是
另外,注意使用这种方式连边需要为
参考代码
#include <bits/stdc++.h>
using namespace std;
int n, k, a[1000024], r[1050024], in[1050024], msv[1050024];
int ev[22000024], ex[22000024], es[1050024], ecnt;
vector<int> ans[24];
void add(int u, int v) {
ev[++ecnt] = v;
ex[ecnt] = es[u];
es[u] = ecnt;
in[v]++;
}
#define lowbit(x) ((x) & -(x))
int main() {
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
r[a[i]] = i;
}
sort(a + 1, a + n + 1);
for (int i = 0; i < (1 << k); i++) {
int tmp = i;
while (tmp) {
int x = lowbit(tmp);
add(i, i - x);
tmp -= x;
}
}
queue<int> q;
q.push((1 << k) - 1);
while (!q.empty()) {
int u = q.front();
q.pop();
int t = r[u];
if (t) ans[msv[u] + 1].push_back(u);
for (int i = es[u]; i; i = ex[i]) {
int v = ev[i];
if (t) msv[v] = max(msv[v], msv[u] + 1);
else msv[v] = max(msv[v], msv[u]);
if (!--in[v]) q.push(v);
}
}
int x = 1;
for (; ans[x].size(); x++);
x--;
printf("1\n%d\n", x);
for (int i = 1; i <= x; i++) {
printf("%d", ans[i].size());
for (auto u : ans[i]) {
printf(" %d", u);
}
puts("");
}
return 0;
}