This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
#ifdef tabr
#include "library/debug.cpp"
#else
#define debug(...)
#endif
// editorial
template <typename T>
struct forest {
struct edge {
int from;
int to;
T cost;
edge(int _from, int _to, T _cost) : from(_from), to(_to), cost(_cost) {}
};
int n;
vector<edge> edges;
vector<vector<int>> g;
vector<int> pv;
vector<int> pe;
vector<int> depth;
vector<int> root;
vector<int> sz;
vector<int> order;
vector<int> beg;
vector<int> end;
vector<T> dist;
forest(int _n) : n(_n) {
g = vector<vector<int>>(n);
init();
}
void init() {
pv = vector<int>(n, -1);
pe = vector<int>(n, -1);
depth = vector<int>(n, -1);
root = vector<int>(n, -1);
sz = vector<int>(n, 0);
order = vector<int>();
beg = vector<int>(n, -1);
end = vector<int>(n, -1);
dist = vector<T>(n, 0);
}
int add(int from, int to, T cost = 1) {
int id = (int) edges.size();
g[from].emplace_back(id);
g[to].emplace_back(id);
edges.emplace_back(from, to, cost);
return id;
}
void do_dfs(int v) {
beg[v] = (int) order.size();
order.emplace_back(v);
sz[v] = 1;
for (int id : g[v]) {
if (id == pe[v]) {
continue;
}
edge e = edges[id];
int to = e.from ^ e.to ^ v;
pv[to] = v;
pe[to] = id;
depth[to] = depth[v] + 1;
root[to] = (root[v] != -1 ? root[v] : to);
dist[to] = dist[v] + e.cost;
do_dfs(to);
sz[v] += sz[to];
}
end[v] = (int) order.size();
}
void dfs(int v) {
pv[v] = -1;
pe[v] = -1;
depth[v] = 0;
root[v] = v;
order.clear();
dist[v] = 0;
do_dfs(v);
}
void dfs_all() {
init();
for (int v = 0; v < n; v++) {
if (depth[v] == -1) {
dfs(v);
}
}
}
int h = -1;
vector<vector<int>> p;
inline void build_lca() {
int max_depth = *max_element(depth.begin(), depth.end());
h = 1;
while ((1 << h) <= max_depth) {
h++;
}
p = vector<vector<int>>(h, vector<int>(n));
p[0] = pv;
for (int i = 1; i < h; i++) {
for (int j = 0; j < n; j++) {
p[i][j] = (p[i - 1][j] == -1 ? -1 : p[i - 1][p[i - 1][j]]);
}
}
}
inline bool anc(int x, int y) { // return x is y's ancestor or not
return (beg[x] <= beg[y] && end[y] <= end[x]);
}
inline int go_up(int x, int up) {
assert(h != -1);
up = min(up, (1 << h) - 1);
for (int i = h - 1; i >= 0; i--) {
if (up & (1 << i)) {
x = p[i][x];
if (x == -1) {
break;
}
}
}
return x;
}
inline int lca(int x, int y) {
assert(h != -1);
if (anc(x, y)) {
return x;
}
if (anc(y, x)) {
return y;
}
for (int i = h - 1; i >= 0; i--) {
if (p[i][x] != -1 && !anc(p[i][x], y)) {
x = p[i][x];
}
}
return p[0][x];
}
inline T distance(int x, int y) {
return dist[x] + dist[y] - 2 * dist[lca(x, y)];
}
};
struct dsu {
vector<int> p;
vector<int> sz;
int n;
dsu(int _n) : n(_n) {
p = vector<int>(n);
iota(p.begin(), p.end(), 0);
sz = vector<int>(n, 1);
}
inline int get(int x) {
if (p[x] == x) {
return x;
} else {
return p[x] = get(p[x]);
}
}
inline bool unite(int x, int y) {
x = get(x);
y = get(y);
if (x == y) {
return false;
}
p[x] = y;
sz[y] += sz[x];
return true;
}
inline bool same(int x, int y) {
return (get(x) == get(y));
}
inline int size(int x) {
return sz[get(x)];
}
inline bool root(int x) {
return (x == get(x));
}
};
struct segtree {
using T = int;
T e() {
return (int) -2e9;
}
T op(T x, T y) {
return max(x, y);
}
int n;
int size;
vector<T> node;
segtree() : segtree(0) {}
segtree(int _n) {
build(vector<T>(_n, e()));
}
segtree(const vector<T> &v) {
build(v);
}
void build(const vector<T> &v) {
n = (int) v.size();
if (n <= 1) {
size = n;
} else {
size = 1 << (32 - __builtin_clz(n - 1));
}
node.resize(2 * size, e());
for (int i = 0; i < n; i++) {
node[i + size] = v[i];
}
for (int i = size - 1; i > 0; i--) {
node[i] = op(node[2 * i], node[2 * i + 1]);
}
}
void set(int p, T v) {
assert(0 <= p && p < n);
p += size;
node[p] = v; // update
// node[p] += v; // add
while (p > 1) {
p >>= 1;
node[p] = op(node[2 * p], node[2 * p + 1]);
}
}
T get(int l, int r) {
assert(0 <= l && l <= r && r <= n);
T vl = e();
T vr = e();
l += size;
r += size;
while (l < r) {
if (l & 1) {
vl = op(vl, node[l++]);
}
if (r & 1) {
vr = op(node[--r], vr);
}
l >>= 1;
r >>= 1;
}
return op(vl, vr);
}
T get(int p) {
assert(0 <= p && p < n);
return node[p + size];
}
};
vector<int> check_validity(int n, vector<int> x, vector<int> y, vector<int> s, vector<int> e, vector<int> l, vector<int> r) {
int m = (int) x.size();
int q = (int) s.size();
vector<vector<int>> g(n);
for (int i = 0; i < m; i++) {
g[x[i]].emplace_back(y[i]);
g[y[i]].emplace_back(x[i]);
}
forest<int> g0(n), g1(n);
dsu uf(n);
for (int i = n - 1; i >= 0; i--) {
for (int j : g[i]) {
if (j > i && !uf.same(i, j)) {
g0.add(i, uf.get(j));
uf.unite(j, i);
}
}
}
g0.dfs(0);
g0.build_lca();
uf = dsu(n);
for (int i = 0; i < n; i++) {
for (int j : g[i]) {
if (i > j && !uf.same(i, j)) {
g1.add(i, uf.get(j));
uf.unite(j, i);
}
}
}
g1.dfs(n - 1);
g1.build_lca();
vector<int> res(q);
for (int i = 0; i < q; i++) {
for (int j = g0.h - 1; j >= 0; j--) {
if (g0.p[j][s[i]] >= l[i]) {
s[i] = g0.p[j][s[i]];
}
}
for (int j = g1.h - 1; j >= 0; j--) {
if (g1.p[j][e[i]] <= r[i] && g1.p[j][e[i]] != -1) {
e[i] = g1.p[j][e[i]];
}
}
}
vector<int> p(n);
for (int i = 0; i < n; i++) {
p[i] = g0.beg[g1.order[i]];
}
vector<int> pos(n);
for (int i = 0; i < n; i++) {
pos[p[i]] = i;
}
debug(g0.order);
debug(g1.order);
debug(p);
segtree seg(n);
vector<vector<int>> event(n);
for (int i = 0; i < q; i++) {
event[g0.end[s[i]] - 1].emplace_back(i);
}
for (int i = 0; i < n; i++) {
seg.set(pos[i], i);
for (int id : event[i]) {
int t = seg.get(g1.beg[e[id]], g1.end[e[id]]);
if (t >= g0.beg[s[id]]) {
res[id] = 1;
}
}
}
return res;
}
#ifdef tabr
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
debug(check_validity(6, {5, 1, 1, 3, 3, 5}, {1, 2, 3, 4, 0, 2}, {4, 4, 5}, {2, 2, 4}, {1, 2, 3}, {2, 2, 4}));
return 0;
}
#endif
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |