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...