#include <bits/stdc++.h>
#ifndef LOCAL
#include "werewolf.h"
#endif
using namespace std;
using ll = long long;
using ld = long double;
using pl = pair<ll,ll>;
using pii = pair<int,int>;
using tpl = tuple<int,int,int>;
#define all(a) a.begin(), a.end()
#define filter(a) a.erase(unique(all(a)), a.end())
struct DSU {
vector<int> lab;
DSU (int sz) : lab(sz + 1, -1) {}
int get (int u) {
if (lab[u] < 0) return u;
return lab[u] = get(lab[u]);
}
int getSz (int u) { return -lab[get(u)]; }
bool unite (int a, int b) {
a = get(a), b = get(b);
if (a == b) return 0;
if (-lab[a] < -lab[b]) swap(a, b);
lab[a] += lab[b], lab[b] = a;
return 1;
}
};
struct queryItem {
int st, en, bound, idx;
queryItem() : st(0), en(0), bound(0), idx(0) {}
queryItem (int st, int en, int bound, int idx) :
st(st), en(en), bound(bound), idx(idx) {}
};
const int mn = 6e5 + 5;
int sz[mn], num[mn], chain[mn], depth[mn], par[mn], weight[mn], top[mn], timeDfs;
vector<int> graphAdj[mn], adj[mn];
vector<queryItem> queries[mn];
// custom comparator for set
struct setComp {
bool operator() (const int &a, const int &b) const { return num[a] < num[b]; }
};
set<int, setComp> markedNode[mn];
void addEdge (int par, int u) {
adj[par].push_back(top[u]);
top[u] = par;
}
int szDfs (int u) {
sz[u] = 1;
for (int v : adj[u]) sz[u] += szDfs(v);
return sz[u];
}
void dfs (int u, int p, int d, bool toP) {
num[u] = ++timeDfs, par[u] = p, depth[u] = d;
chain[u] = (toP ? chain[p] : u);
sort(all(adj[u]), [&] (int a, int b) { return sz[a] > sz[b]; });
bool heavy = 1;
for (int v : adj[u])
dfs(v, u, d + 1, heavy), heavy = 0;
}
int lca (int a, int b) {
int ap = par[chain[a]], bp = par[chain[b]];
while (chain[a] != chain[b]) {
if (depth[ap] == depth[bp]) {
a = ap, ap = par[chain[a]];
b = bp, bp = par[chain[b]];
}
else if (depth[ap] > depth[bp]) a = ap, ap = par[chain[a]];
else if (depth[bp] > depth[ap]) b = bp, bp = par[chain[b]];
}
return (depth[a] < depth[b] ? a : b);
}
vector<int> check_validity (int N, vector<int> X, vector<int> Y, vector<int> S, vector<int> E, vector<int> L, vector<int> R) {
/// process input and prepare offline queries
// int M = sizeof(X) / sizeof(X[0]), Q = sizeof(S) / sizeof(S[0]);
int M = X.size(), Q = S.size();
for (int i = 0; i < M; i++) {
graphAdj[X[i]].push_back(Y[i]);
graphAdj[Y[i]].push_back(X[i]);
}
for (int i = 0; i < Q; i++)
queries[L[i]].emplace_back(S[i], E[i], R[i], i);
/// build DSU tree for MST (with Kruskal)
int node = N - 1; DSU dsu(N);
for (int i = 0; i < N; i++) top[i] = weight[i] = i;
for (int i = 0; i < N; i++) {
bool firstMerge = 1;
for (int j : graphAdj[i]) {
int u = dsu.get(i), v = dsu.get(j);
if (j > i || !dsu.unite(i, j)) continue;
if (firstMerge)
firstMerge = 0, addEdge(++node, u);
addEdge(node, v);
}
if (!firstMerge) weight[node] = i;
}
/// process DSU tree
szDfs(node), dfs(node, node + 1, 1, 0);
/// build MST (max) and process queries
vector<int> res(Q);
dsu = DSU(N);
for (int i = 0; i < N; i++) markedNode[i].insert(i);
for (int i = N - 1; i >= 0; i--) {
for (int j : graphAdj[i]) {
int u = dsu.get(i), v = dsu.get(j);
if (j > i && dsu.unite(i, j)) {
if (u == dsu.get(i)) swap(u, v);
for (int iter : markedNode[u])
markedNode[v].insert(iter);
markedNode[u].clear();
}
}
for (queryItem &iter : queries[i]) {
int root = dsu.get(iter.st), opt = INT_MAX;
auto it = markedNode[root].lower_bound(iter.en);
if (it != markedNode[root].end()) {
int lc = lca(iter.en, *it);
opt = min(opt, weight[lc]);
}
if (it != markedNode[root].begin()) {
int lc = lca(iter.en, *prev(it));
opt = min(opt, weight[lc]);
}
res[iter.idx] = (opt <= iter.bound);
}
}
return res;
}
#ifdef LOCAL
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
vector<int> X = {5, 1, 1, 3, 3, 5};
vector<int> Y = {1, 2, 3, 4, 0, 2};
vector<int> S = {4, 4, 5};
vector<int> E = {2, 2, 4};
vector<int> L = {1, 2, 3};
vector<int> R = {2, 2, 4};
vector<int> res = check_validity(6, X, Y, S, E, L, R);
for (int u : res) cout << u << " ";
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... |