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>
#ifndef LOCAL
#include "circuit.h"
#endif // LOCAL
using namespace std;
#define rep(i, l, r) for(int i = (l), _r = (r); i < _r; ++i)
#define FOR(i, l, r) for(int i = (l), _r = (r); i <= _r; ++i)
#define ROF(i, r, l) for(int i = (r), _l = (l); i >= _l; --i)
#define all(v) begin(v), end(v)
#define compact(v) v.erase(unique(all(v)), end(v))
#define sz(v) (int)v.size()
#define dbg(x) "[" #x " = " << (x) << "]"
#define file(name) if(fopen(name".inp", "r")) freopen(name".inp", "r", stdin), freopen(name".out", "w", stdout);
template<typename T>
bool minimize(T& a, const T& b){
if(a > b) return a = b, true; return false;
}
template<typename T>
bool maximize(T& a, const T& b){
if(a < b) return a = b, true; return false;
}
using ll = long long;
using ld = long double;
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
template<typename T> T random_int(T l, T r){ return uniform_int_distribution<T>(l, r)(rng); }
template<typename T> T random_real(T l, T r){ return uniform_real_distribution<T>(l, r)(rng); }
const int MAX = 2e5 + 5;
const int mod = 1e9 + 2022;
int n, m;
vector<int> adj[MAX];
bool state[MAX];
int dp[MAX][2], total_ways[MAX], eval[MAX];
int add(int a, int b){
return a + b < mod ? a + b : a + b - mod;
}
int multiply(int a, int b){
return 1LL * a * b % mod;
}
int subtract(int a, int b){
return a < b ? a - b + mod : a - b;
}
bool isLeaf(int u){
return n <= u;
}
struct node{
int total, one;
node(int total = 0, int one = 0) : total(total), one(one) {}
void flip(){ one = subtract(total, one); }
friend node operator + (const node& a, const node& b){
return node(add(a.total, b.total), add(a.one, b.one));
}
};
namespace SegmentTree{
node st[MAX << 1];
int lazy[MAX << 1];
void build(int id, int l, int r){
if(l == r){
st[id] = node(eval[l], (int)state[l] * eval[l]);
} else{
int mid = l + r >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
st[id] = st[id << 1] + st[id << 1 | 1];
}
}
void apply(int id){
st[id].flip();
lazy[id] ^= 1;
}
void lazyDown(int id){
if(lazy[id]){
apply(id << 1);
apply(id << 1 | 1);
lazy[id] = 0;
}
}
void update(int id, int l, int r, int u, int v){
if(u <= l && r <= v) apply(id);
else{
int mid = l + r >> 1;
lazyDown(id);
if(u <= mid) update(id << 1, l, mid, u, v);
if(mid < v) update(id << 1 | 1, mid + 1, r, u, v);
st[id] = st[id << 1] + st[id << 1 | 1];
}
}
int get(){
return st[1].one;
}
}
void predfs(int u){
if(isLeaf(u)){
total_ways[u] = 1;
return;
}
total_ways[u] = sz(adj[u]);
for(int v : adj[u]){
predfs(v);
total_ways[u] = multiply(total_ways[u], total_ways[v]);
}
}
void dfs(int u, int mult){
if(isLeaf(u)){
eval[u - n] = mult;
return;
}
int k = sz(adj[u]);
vector<int> pref(k), suff(k);
for(int i = 0; i < k; ++i){
pref[i] = suff[i] = total_ways[adj[u][i]];
}
for(int i = 1; i < k; ++i){
pref[i] = multiply(pref[i - 1], pref[i]);
}
for(int i = k - 2; i >= 0; --i){
suff[i] = multiply(suff[i], suff[i + 1]);
}
for(int i = 0; i < k; ++i){
int cur = multiply(i > 0 ? pref[i - 1] : 1, i + 1 < k ? suff[i + 1] : 1);
dfs(adj[u][i], multiply(mult, cur));
}
}
void init(int N, int M, vector<int> P, vector<int> A){
n = N;
m = M;
rep(i, 1, n + m){
adj[P[i]].push_back(i);
}
rep(i, 0, m){
state[i] = A[i];
}
predfs(0);
dfs(0, 1);
SegmentTree::build(1, 0, m - 1);
}
int count_ways(int L, int R){
L -= n; R -= n;
SegmentTree::update(1, 0, m - 1, L, R);
return SegmentTree::get();
}
#ifdef LOCAL
int main(){
srand(time(nullptr));
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
auto random = [&](int l, int r){
return uniform_int_distribution<int>(l, r)(rng);
};
for(int itest = 1; itest <= 1; ++itest){
//random testcase
// int N = random(1, 6), M = random(1, 20), Q = random(1, 5);
// cout << "N = " << N << ", M = " << M << ", Q = " << Q << '\n';
// vector<int> P(N + M, -1);
// rep(i, 1, N + M){
// P[i] = random(0, min(i - 1, N - 1));
// }
//
// vector<int> A(M);
// rep(i, 0, M){
// A[i] = random(0, 1);
// }
// cout << "Array P : "; rep(i, 0, N + M) cout << P[i] << ' '; cout << '\n';
// cout << "Array A : "; rep(i, 0, M) cout << A[i] << ' '; cout << '\n';
// init(N, M, P, A);
// rep(i, 0, Q){
// int L = random(0, M - 1), R = random(0, M - 1);
// if(L > R) swap(L, R);
// cout << "query : " << L << ' ' << R << '\n';
// cout << count_ways(L, R) << '\n';
// }
//example testcase
int N = 3, M = 4;
vector<int> P(N + M);
P = {-1, 0, 1, 2, 1, 1, 0};
vector<int> A(M);
A = {1, 0, 1, 0};
init(N, M, P, A);
cout << count_ways(3, 4) << '\n'; //should be 2
cout << count_ways(4, 5) << '\n'; //should be 0
cout << count_ways(3, 6) << '\n'; //should 6
}
return 0;
}
#endif //LOCAL
Compilation message (stderr)
circuit.cpp: In function 'bool minimize(T&, const T&)':
circuit.cpp:20:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
20 | if(a > b) return a = b, true; return false;
| ^~
circuit.cpp:20:35: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
20 | if(a > b) return a = b, true; return false;
| ^~~~~~
circuit.cpp: In function 'bool maximize(T&, const T&)':
circuit.cpp:25:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
25 | if(a < b) return a = b, true; return false;
| ^~
circuit.cpp:25:35: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
25 | if(a < b) return a = b, true; return false;
| ^~~~~~
circuit.cpp: In function 'void SegmentTree::build(int, int, int)':
circuit.cpp:77:25: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
77 | int mid = l + r >> 1;
| ~~^~~
circuit.cpp: In function 'void SegmentTree::update(int, int, int, int, int)':
circuit.cpp:100:25: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
100 | int mid = l + r >> 1;
| ~~^~~
# | 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... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |