QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#118873 | #5445. Vulpecula | hos_lyric | RE | 1ms | 3744kb | C++14 | 6.6kb | 2023-07-04 14:44:27 | 2023-07-04 14:44:28 |
Judging History
answer
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
// (without edge property)
// sub[u]: inside subtree at u, rooted at u
// bus[u]: outside subtree at u, rooted at par[u]
// tot[u]: rooted at u
// T: monoid representing information of a subtree.
// T::init() should assign the identity.
// T::pull(const T &l, const T &r) should assign the product.
// T::up(int u) should attach vertex u to the product of the subtrees.
template <class T> struct ForestDP {
int n;
vector<vector<int>> graph;
vector<int> par;
vector<T> sub, bus, tot;
ForestDP() : n(0) {}
explicit ForestDP(int n_) : n(n_), graph(n_) {}
void ae(int u, int v) {
assert(0 <= u); assert(u < n);
assert(0 <= v); assert(v < n);
graph[u].push_back(v);
graph[v].push_back(u);
}
void run() {
par.assign(n, -2);
sub.resize(n);
bus.resize(n);
tot.resize(n);
for (int u = 0; u < n; ++u) if (par[u] == -2) {
dfs0(u, -1);
dfs1(u, -1);
}
}
void dfs0(int u, int p) {
par[u] = p;
const int deg = graph[u].size();
int w = -1;
for (int j = deg; --j >= 0; ) {
const int v = graph[u][j];
if (p != v) {
dfs0(v, u);
if (~w) {
bus[v].pull(sub[v], bus[w]);
} else {
bus[v] = sub[v];
}
w = v;
}
}
if (~w) {
sub[u] = bus[w];
} else {
sub[u].init();
}
sub[u].up(u);
}
void dfs1(int u, int p) {
const int deg = graph[u].size();
int v = -1;
for (int j = 0; j < deg; ++j) {
const int w = graph[u][j];
if (p != w) {
if (~v) {
bus[v].pull(tot[v], bus[w]);
bus[v].up(u);
tot[w].pull(tot[v], sub[v]);
dfs1(v, u);
} else {
if (~p) {
tot[w] = bus[u];
} else {
tot[w].init();
}
}
v = w;
}
}
if (~v) {
bus[v] = tot[v];
bus[v].up(u);
tot[u].pull(tot[v], sub[v]);
dfs1(v, u);
} else {
if (~p) {
tot[u] = bus[u];
} else {
tot[u].init();
}
}
tot[u].up(u);
}
};
////////////////////////////////////////////////////////////////////////////////
using U = unsigned long long;
#ifdef LOCAL
constexpr int E = 7;
#else
constexpr int E = 64;
#endif
// https://qoj.ac/problem/5445
// given basis of two spaces, returns nonzero when their intersection increases
struct Intersection {
// len = dim(their sum)
int len;
U as[E], bs[E];
Intersection() : len(0) {}
U add(U a, U b) {
for (int i = 0; i < len; ++i) if (chmin(a, a ^ as[i])) b ^= bs[i];
if (a) {
as[len] = a; bs[len] = b; ++len; return 0;
} else {
return b;
}
}
U add0(U a) { return add(a, 0); }
U add1(U a) { return add(a, a); }
};
Intersection I;
int N;
vector<int> P;
vector<int> M;
vector<vector<U>> X;
struct Data {
// (d, x): at depth d, add x to ann
int len;
pair<int, U> ps[E];
// identity: full space
void init() {
len = E;
for (int e = 0; e < E; ++e) ps[e] = make_pair(N - 1, 1ULL << e);
}
void pull(const Data &a, const Data &b) {
len = 0;
I.len = 0;
for (int i = 0, j = 0; i < a.len || j < b.len; ) {
if (i < a.len && ((j == b.len || a.ps[i].first >= b.ps[j].first))) {
const U y = I.add0(a.ps[i].second);
if (y) ps[len++] = make_pair(a.ps[i].first, y);
++i;
} else {
const U y = I.add1(b.ps[j].second);
if (y) ps[len++] = make_pair(b.ps[j].first, y);
++j;
}
}
// cerr<<"a = ";pv(a.ps,a.ps+a.len);
// cerr<<"b = ";pv(b.ps,b.ps+b.len);
// cerr<<" -> ";pv(ps,ps+len);
}
void up(int u) {
const Data a = *this;
len = 0;
I.len = 0;
for (const U x : X[u]) {
I.add0(x);
}
for (int i = 0; i < a.len; ++i) {
const U y = I.add1(a.ps[i].second);
if (y) ps[len++] = make_pair(min(1 + a.ps[i].first, N - 1), y);
}
for (const U x : X[u]) {
U y = x;
for (int i = 0; i < len; ++i) chmin(y, y ^ ps[i].second);
if (y) ps[len++] = make_pair(0, y);
}
// cerr<<"up "<<u<<" "<<X[u]<<endl;
// cerr<<" a = ";pv(a.ps,a.ps+a.len);
// cerr<<" -> ";pv(ps,ps+len);
}
U solve() const {
// pv(ps,ps+len);
U ans = 0;
int d = N - 1;
U now = 0;
for (int i = 0; i < len; ++i) {
ans += (d - ps[i].first) * now;
d = ps[i].first;
chmax(now, now ^ ps[i].second);
}
ans += (d - (-1)) * now;
return ans;
}
};
int main() {
for (; ~scanf("%d", &N); ) {
P.assign(N, -1);
for (int u = 1; u < N; ++u) {
scanf("%d", &P[u]);
--P[u];
}
M.resize(N);
X.resize(N);
for (int u = 0; u < N; ++u) {
scanf("%d", &M[u]);
X[u].resize(M[u]);
for (U &x : X[u]) {
scanf("%llu", &x);
}
}
int dim;
U basis[E];
for (int u = 0; u < N; ++u) {
dim = 0;
for (const U x : X[u]) {
U y = x;
for (int i = 0; i < dim; ++i) {
chmin(y, y ^ basis[i]);
}
if (y) {
basis[dim++] = y;
}
}
X[u] = vector<U>(basis, basis + dim);
}
ForestDP<Data> f(N);
for (int u = 1; u < N; ++u) {
f.ae(P[u], u);
}
f.run();
for (int u = 0; u < N; ++u) {
const U ans = f.tot[u].solve();
printf("%llu\n", ans);
}
}
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 1ms
memory: 3684kb
input:
2 1 2 2 3 2 1 1
output:
4 2
result:
ok 2 lines
Test #2:
score: 0
Accepted
time: 1ms
memory: 3744kb
input:
5 1 2 2 3 3 83 75 58 4 125 124 58 16 4 39 125 71 112 3 69 66 5 4 48 73 69 6
output:
171 125 183 142 243
result:
ok 5 lines
Test #3:
score: 0
Accepted
time: 0ms
memory: 3668kb
input:
2 1 0 0
output:
0 0
result:
ok 2 lines
Test #4:
score: -100
Runtime Error
input:
500 1 2 3 2 1 2 6 2 4 6 6 10 7 12 7 9 8 10 12 20 12 19 15 24 25 23 25 22 29 29 28 26 31 25 34 31 35 33 39 37 36 42 37 37 41 43 42 46 45 45 49 52 53 50 46 50 49 52 58 57 57 61 57 59 56 65 63 59 66 65 63 70 70 68 72 71 73 72 72 76 72 75 80 76 76 82 83 80 89 89 91 85 85 90 89 89 89 92 93 91 92 93 98 96...