#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
// mt19937 engine((unsigned ll)time(NULL));
// uniform_int_distribution<ll> distribution(0, (ll)1e18);
// auto generator = bind(distribution, engine);
// ll x = generator();
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
// #define ordered_set tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update>
// #define ordered_multiset tree<int, null_type, less_equal<int>, rb_tree_tag,tree_order_statistics_node_update>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using vi = std::vector<int>;
using vvi = std::vector<vi>;
using vl = std::vector<ll>;
using vii = std::vector<pair<int, int> >;
using vvl = std::vector<vl>;
using vll = std::vector<pair<ll , ll> >;
using vd = std::vector<double>;
using vvd = std::vector<vd>;
using vs = std::vector<std::string>;
using vvs = std::vector<vs>;
using vb = std::vector<bool>;
using vvb = std::vector<vb>;
using vc = std::vector<char>;
using vvc = std::vector<vc>;
using pii = std::pair<int, int>;
using pll = std::pair<ll, ll>;
using piil = std::pair<pair<int, int>, ll>;
using mii = std::map<int, int>;
using mll = std::map<ll, ll>;
using pql = std::priority_queue<ll>;
using pqi = std::priority_queue<int>;
using pqiil = std::priority_queue<pair<pair<int, int>, ll> >;
using pqii = std::priority_queue<pair<int, int> >;
#define pb push_back
#define ps push
#define eb emplace_back
#define is insert
#define er erase
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define sf(i) sizeof(i)
#define endl "\n"
#define all(v) (v).begin(), (v).end()
#define rep(i, L, R) for(ll i = L;i<=R;i++)
#define pcis precision
#define sz(a) ((ll) a.size())
template<typename T>
struct infinity {
static constexpr T max=std::numeric_limits<T>::max();
static constexpr T min=std::numeric_limits<T>::min();
static constexpr T value=std::numeric_limits<T>::max()/2;
static constexpr T mvalue=std::numeric_limits<T>::min()/2;
};
template<typename T>constexpr T INF=infinity<T>::value;
constexpr ll lINF=INF<ll>;
constexpr int iINF = INF<int>;
constexpr ld PI = 3.1415926535897932384626;
#include "joitour.h"
struct Fenwick {
int n;
vector<ll> f;
void init(int _n) {
n = _n;
f.assign(n+1, 0);
}
// add v at index i (0-based)
void update(int i, ll v) {
for (int x = i+1; x <= n; x += x & -x)
f[x] += v;
}
// sum on [0..i]
ll query(int i) const {
ll s = 0;
for (int x = i+1; x > 0; x -= x & -x)
s += f[x];
return s;
}
// sum on [l..r]
ll range_sum(int l, int r) const {
if (l > r) return 0;
return query(r) - (l>0 ? query(l-1) : 0);
}
};
int N, Q;
vector<vector<int>> adj;
vector<int> F;
vector<int> tin, tout, parent;
int timer;
Fenwick bitJ, bitI;
ll totJ=0, totI=0, totO=0;
vector<ll> sg;
ll ans = 0;
// build Euler tour indices and parent[], iterative DFS
void build_euler() {
tin.assign(N, 0);
tout.assign(N, 0);
parent.assign(N, -1);
timer = 0;
// stack of (u, parent, state, next_child_index)
struct Item {
int u, p, state, idx;
};
vector<Item> st;
st.reserve(2*N);
st.push_back({0, -1, 0, 0});
while (!st.empty()) {
auto &it = st.back();
int u = it.u, p = it.p, state = it.state, &i = it.idx;
if (state == 0) {
// enter
parent[u] = p;
tin[u] = timer++;
it.state = 1;
i = 0;
} else if (i < (int)adj[u].size()) {
int v = adj[u][i++];
if (v == p) continue;
st.push_back({v, u, 0, 0});
} else {
// exit
tout[u] = timer;
st.pop_back();
}
}
}
// calculate sg[u] = totJ*totI - sum_{each comp when u removed} (J_comp * I_comp)
ll calc_sg(int u) {
ll bad = 0;
// for each neighbor, compute that component's J,I
for (int v: adj[u]) {
ll Jv, Iv;
if (v == parent[u]) {
// outside component = all minus subtree of u
ll subJ = bitJ.range_sum(tin[u], tout[u]-1);
ll subI = bitI.range_sum(tin[u], tout[u]-1);
Jv = totJ - subJ;
Iv = totI - subI;
} else {
// child subtree
Jv = bitJ.range_sum(tin[v], tout[v]-1);
Iv = bitI.range_sum(tin[v], tout[v]-1);
}
bad += Jv * Iv;
}
return totJ * totI - bad;
}
void init(int n, vector<int> F_, vector<int> U, vector<int> V, int Q_) {
N = n;
Q = Q_;
F = F_;
adj.assign(N, {});
for (int j = 0; j < N-1; j++) {
adj[U[j]].push_back(V[j]);
adj[V[j]].push_back(U[j]);
}
build_euler();
bitJ.init(N);
bitI.init(N);
// global counts and Fenwick initial update
totJ = totI = totO = 0;
for (int i = 0; i < N; i++) {
if (F[i] == 0) {
totJ++;
bitJ.update(tin[i], +1);
}
if (F[i] == 2) {
totI++;
bitI.update(tin[i], +1);
}
if (F[i] == 1) {
totO++;
}
}
sg.assign(N, 0);
ans = 0;
// compute initial sg for omelette nodes
for (int u = 0; u < N; u++) {
if (F[u] == 1) {
sg[u] = calc_sg(u);
ans += sg[u];
}
}
}
void change(int X, int Y) {
// if X was omelette, remove its contribution
if (F[X] == 1) {
ans -= sg[X];
}
// remove old type from counts & Fenwick
if (F[X] == 0) {
totJ--;
bitJ.update(tin[X], -1);
}
if (F[X] == 2) {
totI--;
bitI.update(tin[X], -1);
}
if (F[X] == 1) {
totO--;
}
// update type
F[X] = Y;
// add new type
if (F[X] == 0) {
totJ++;
bitJ.update(tin[X], +1);
}
if (F[X] == 2) {
totI++;
bitI.update(tin[X], +1);
}
if (F[X] == 1) {
totO++;
}
// recompute sg for X and its neighbors
vector<int> touch;
touch.reserve(adj[X].size()+1);
touch.push_back(X);
for (int v: adj[X]) touch.push_back(v);
for (int u: touch) {
if (F[u] == 1) {
ll old = sg[u];
ll now = calc_sg(u);
sg[u] = now;
ans += (now - old);
}
}
}
ll num_tours() {
return ans;
}
//void _main();
//int main() {
// _main();
// return 0;
//}
//void _main() {
//
//
//
//}
# | 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... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |