Submission #808661

#TimeUsernameProblemLanguageResultExecution timeMemory
808661alex_2008Digital Circuit (IOI22_circuit)C++17
61 / 100
3019 ms7848 KiB
#include "circuit.h" #include <cmath> #include <algorithm> #include <vector> #include <iostream> using namespace std; typedef long long ll; int NN, MM; const ll N = 2e5 + 10, mod = 1000002022; int p[N], d[N]; int lazy[4 * N]; int a[N], cnt[N]; ll pref[N]; bool ch = true, ch2 = true; pair <ll, ll> tree[4 * N]; ll tree2[4 * N]; ll binpow(ll a, ll n) { if (n == 0) return 1LL; if (n % 2 == 0) { ll u = binpow(a, n / 2); return (u * u) % mod; } return (a * binpow(a, n - 1)) % mod; } void pushh(int v, int tl, int tr) { if (lazy[v]) { lazy[v] = 0; if (tl != tr) { lazy[2 * v] = (lazy[2 * v] + 1) % 2; lazy[2 * v + 1] = (lazy[2 * v + 1] + 1) % 2; swap(tree[2 * v].first, tree[2 * v].second); swap(tree[2 * v + 1].first, tree[2 * v + 1].second); } } } void build_tree(int v, int tl, int tr) { if (tl == tr) { if (a[tl] == 1) tree[v] = { 1, 0 }; else tree[v] = { 0, 1 }; } else { int tm = (tl + tr) / 2; build_tree(2 * v, tl, tm); build_tree(2 * v + 1, tm + 1, tr); ll a = tree[2 * v].first, b = tree[2 * v].second, c = tree[2 * v + 1].first, d = tree[2 * v + 1].second; tree[v].first = 2 * a * c + a * d + b * c; tree[v].second = 2 * b * d + a * d + b * c; tree[v].first %= mod; tree[v].second %= mod; } } void update(int v, int tl, int tr, int l, int r) { if (tl > r || tr < l) return; if (tl >= l && tr <= r) { lazy[v] = (lazy[v] + 1) % 2; swap(tree[v].first, tree[v].second); return; } pushh(v, tl, tr); int tm = (tl + tr) / 2; update(2 * v, tl, tm, l, r); update(2 * v + 1, tm + 1, tr, l, r); ll a = tree[2 * v].first, b = tree[2 * v].second, c = tree[2 * v + 1].first, d = tree[2 * v + 1].second; tree[v].first = 2 * a * c + a * d + b * c; tree[v].second = 2 * b * d + a * d + b * c; tree[v].first %= mod; tree[v].second %= mod; } void build_tree2(int v, int tl, int tr) { if (tl == tr) { if (a[tl]) { tree2[v] = pref[tl]; if (tl) tree2[v] -= pref[tl - 1]; tree2[v] = (tree2[v] + mod) % mod; } else tree2[v] = 0; } else { int tm = (tl + tr) / 2; build_tree2(2 * v, tl, tm); build_tree2(2 * v + 1, tm + 1, tr); tree2[v] = tree2[2 * v] + tree2[2 * v + 1]; tree2[v] %= mod; } } void pushh2(int v, int tl, int tr) { if (lazy[v]) { lazy[v] = 0; if (tl != tr) { lazy[2 * v] = (lazy[2 * v] + 1) % 2; lazy[2 * v + 1] = (lazy[2 * v + 1] + 1) % 2; int tm = (tl + tr) / 2; ll u = pref[tm]; if (tl) u -= pref[tl - 1]; u += mod; u %= mod; tree2[2 * v] = (u + mod - tree2[2 * v]) % mod; u = pref[tr] - pref[tm] + mod; u %= mod; tree2[2 * v + 1] = (u + mod - tree2[2 * v + 1]) % mod; } } } void update2(int v, int tl, int tr, int l, int r) { if (tl > r || tr < l) return; if (tl >= l && tr <= r) { lazy[v] = (lazy[v] + 1) % 2; ll u = pref[tr]; if (tl) u -= pref[tl - 1]; u += mod; u %= mod; tree2[v] = (u - tree2[v] + mod) % mod; return; } pushh2(v, tl, tr); int tm = (tl + tr) / 2; update2(2 * v, tl, tm, l, r); update2(2 * v + 1, tm + 1, tr, l, r); tree2[v] = tree2[2 * v] + tree2[2 * v + 1]; tree2[v] %= mod; } pair<ll, ll> dp[N]; vector <vector<int>> G; void dfs(int v, int p) { vector <int> childrens; for (auto it : G[v]) { if (it == p) continue; dfs(it, v); childrens.push_back(it); } if (childrens.empty()) { dp[v].first = 1; dp[v].second = 0; if (a[v - NN] == 0) swap(dp[v].first, dp[v].second); return; } vector <vector<ll>> w((int)childrens.size()); for (int i = 0; i < (int)w.size(); i++) { w[i].resize(i + 2); } w[0][0] = dp[childrens[0]].second; w[0][1] = dp[childrens[0]].first; for (int i = 1; i < (int)childrens.size(); i++) { for (int j = 0; j <= i + 1; j++) { w[i][j] = 0; if (j != i + 1) w[i][j] += w[i - 1][j] * dp[childrens[i]].second; if (j > 0) w[i][j] += w[i - 1][j - 1] * dp[childrens[i]].first; w[i][j] %= mod; } } ll ff = 0, ss = 0; for (int j = 0; j <= (int)childrens.size(); j++) { ll u = w[(int)childrens.size() - 1][j] * (ll(j)); u %= mod; ff += u; ff %= mod; u = w[(int)childrens.size() - 1][j] * ((ll)childrens.size() - ll(j)); u %= mod; ss += u; ss %= mod; } dp[v].first = ff; dp[v].second = ss; } void init(int N, int M, std::vector<int> P, std::vector<int> A) { NN = N, MM = M; for (int i = 0; i < N + M; i++) { p[i] = P[i]; if (i == 0) d[0] = 0; if (i > 0 && p[i] != (i - 1) / 2) ch = false; if (i) { d[i] = d[P[i]] + 1; cnt[P[i]]++; } } for (int i = 0; i < N; i++) { if (cnt[i] != 2) ch2 = false; } for (int i = 0; i < M; i++) { a[i] = A[i]; } if (M != N + 1) ch = false; int u = log2(M); if ((1 << u) != M) ch = false; if (ch) build_tree(1, 0, M - 1); else if (ch2) { for (int i = 0; i < M; i++) { pref[i] = binpow(2, N - d[i + N]); if (i) pref[i] += pref[i - 1]; pref[i] %= mod; } build_tree2(1, 0, MM - 1); } else { G.resize(N + M); for (int i = 1; i < N + M; i++) { G[p[i]].push_back(i); } dfs(0, -1); } } int count_ways(int L, int R) { if (ch) { update(1, 0, MM - 1, L - NN, R - NN); return tree[1].first; } else if (ch2) { update2(1, 0, MM - 1, L - NN, R - NN); return tree2[1]; } else { for (int i = L - NN; i <= R - NN; i++) { a[i] = (a[i] + 1) % 2; } dfs(0, -1); return dp[0].first; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...