This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// correct/solution-jonathanirvings.cpp
#include "circuit.h"
#include <bits/stdc++.h>
using namespace std;
#ifndef ATCODER_INTERNAL_BITOP_HPP
#define ATCODER_INTERNAL_BITOP_HPP 1
#ifdef _MSC_VER
#include <intrin.h>
#endif
namespace atcoder {
namespace internal {
// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
int x = 0;
while ((1U << x) < (unsigned int)(n)) x++;
return x;
}
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
constexpr int bsf_constexpr(unsigned int n) {
int x = 0;
while (!(n & (1 << x))) x++;
return x;
}
// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
unsigned long index;
_BitScanForward(&index, n);
return index;
#else
return __builtin_ctz(n);
#endif
}
} // namespace internal
} // namespace atcoder
#endif // ATCODER_INTERNAL_BITOP_HPP
#ifndef ATCODER_LAZYSEGTREE_HPP
#define ATCODER_LAZYSEGTREE_HPP 1
#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>
namespace atcoder {
template <class S,
S (*op)(S, S),
S (*e)(),
class F,
S (*mapping)(F, S),
F (*composition)(F, F),
F (*id)()>
struct lazy_segtree {
public:
lazy_segtree() : lazy_segtree(0) {}
explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
explicit lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
log = internal::ceil_pow2(_n);
size = 1 << log;
d = std::vector<S>(2 * size, e());
lz = std::vector<F>(size, id());
for (int i = 0; i < _n; i++) d[size + i] = v[i];
for (int i = size - 1; i >= 1; i--) {
update(i);
}
}
void set(int p, S x) {
assert(0 <= p && p < _n);
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
d[p] = x;
for (int i = 1; i <= log; i++) update(p >> i);
}
S get(int p) {
assert(0 <= p && p < _n);
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
return d[p];
}
S prod(int l, int r) {
assert(0 <= l && l <= r && r <= _n);
if (l == r) return e();
l += size;
r += size;
for (int i = log; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
S sml = e(), smr = e();
while (l < r) {
if (l & 1) sml = op(sml, d[l++]);
if (r & 1) smr = op(d[--r], smr);
l >>= 1;
r >>= 1;
}
return op(sml, smr);
}
S all_prod() { return d[1]; }
void apply(int p, F f) {
assert(0 <= p && p < _n);
p += size;
for (int i = log; i >= 1; i--) push(p >> i);
d[p] = mapping(f, d[p]);
for (int i = 1; i <= log; i++) update(p >> i);
}
void apply(int l, int r, F f) {
assert(0 <= l && l <= r && r <= _n);
if (l == r) return;
l += size;
r += size;
for (int i = log; i >= 1; i--) {
if (((l >> i) << i) != l) push(l >> i);
if (((r >> i) << i) != r) push((r - 1) >> i);
}
{
int l2 = l, r2 = r;
while (l < r) {
if (l & 1) all_apply(l++, f);
if (r & 1) all_apply(--r, f);
l >>= 1;
r >>= 1;
}
l = l2;
r = r2;
}
for (int i = 1; i <= log; i++) {
if (((l >> i) << i) != l) update(l >> i);
if (((r >> i) << i) != r) update((r - 1) >> i);
}
}
template <bool (*g)(S)> int max_right(int l) {
return max_right(l, [](S x) { return g(x); });
}
template <class G> int max_right(int l, G g) {
assert(0 <= l && l <= _n);
assert(g(e()));
if (l == _n) return _n;
l += size;
for (int i = log; i >= 1; i--) push(l >> i);
S sm = e();
do {
while (l % 2 == 0) l >>= 1;
if (!g(op(sm, d[l]))) {
while (l < size) {
push(l);
l = (2 * l);
if (g(op(sm, d[l]))) {
sm = op(sm, d[l]);
l++;
}
}
return l - size;
}
sm = op(sm, d[l]);
l++;
} while ((l & -l) != l);
return _n;
}
template <bool (*g)(S)> int min_left(int r) {
return min_left(r, [](S x) { return g(x); });
}
template <class G> int min_left(int r, G g) {
assert(0 <= r && r <= _n);
assert(g(e()));
if (r == 0) return 0;
r += size;
for (int i = log; i >= 1; i--) push((r - 1) >> i);
S sm = e();
do {
r--;
while (r > 1 && (r % 2)) r >>= 1;
if (!g(op(d[r], sm))) {
while (r < size) {
push(r);
r = (2 * r + 1);
if (g(op(d[r], sm))) {
sm = op(d[r], sm);
r--;
}
}
return r + 1 - size;
}
sm = op(d[r], sm);
} while ((r & -r) != r);
return 0;
}
private:
int _n, size, log;
std::vector<S> d;
std::vector<F> lz;
void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
void all_apply(int k, F f) {
d[k] = mapping(f, d[k]);
if (k < size) lz[k] = composition(f, lz[k]);
}
void push(int k) {
all_apply(2 * k, lz[k]);
all_apply(2 * k + 1, lz[k]);
lz[k] = id();
}
};
} // namespace atcoder
#endif // ATCODER_LAZYSEGTREE_HPP
template <int Mod>
struct ModInt {
ModInt() : num_(0) {}
template <class T>
ModInt(T num) {
long long x = (long long)(num % (long long)(Mod));
if (x < 0) x += Mod;
num_ = (int)(x);
}
ModInt& operator++() {
num_++;
if (num_ == Mod) num_ = 0;
return *this;
}
ModInt& operator--() {
if (num_ == 0) num_ = Mod;
num_--;
return *this;
}
ModInt operator++(int) {
ModInt result = *this;
++*this;
return result;
}
ModInt operator--(int) {
ModInt result = *this;
--*this;
return result;
}
ModInt& operator+=(const ModInt& rhs) {
num_ += rhs.num_;
if (num_ >= Mod) num_ -= Mod;
return *this;
}
ModInt& operator-=(const ModInt& rhs) {
num_ -= rhs.num_;
if (num_ < 0) num_ += Mod;
return *this;
}
ModInt& operator*=(const ModInt& rhs) {
long long z = num_;
z *= rhs.num_;
num_ = (int)(z % Mod);
return *this;
}
ModInt& operator/=(const ModInt& rhs) { return *this = *this * rhs.inv(); }
ModInt operator+() const { return *this; }
ModInt operator-() const { return ModInt() - *this; }
ModInt pow(long long n) const {
assert(0 <= n);
ModInt x = *this, r = 1;
while (n) {
if (n & 1) r *= x;
x *= x;
n >>= 1;
}
return r;
}
ModInt inv() const {
return pow(Mod - 2);
}
friend ModInt operator+(const ModInt& lhs, const ModInt& rhs) {
return ModInt(lhs) += rhs;
}
friend ModInt operator-(const ModInt& lhs, const ModInt& rhs) {
return ModInt(lhs) -= rhs;
}
friend ModInt operator*(const ModInt& lhs, const ModInt& rhs) {
return ModInt(lhs) *= rhs;
}
friend ModInt operator/(const ModInt& lhs, const ModInt& rhs) {
return ModInt(lhs) /= rhs;
}
friend bool operator==(const ModInt& lhs, const ModInt& rhs) {
return lhs.num_ == rhs.num_;
}
friend bool operator!=(const ModInt& lhs, const ModInt& rhs) {
return lhs.num_ != rhs.num_;
}
int get() const { return num_; }
int num_;
};
using Int = ModInt<1'000'002'022>;
using Node = pair<Int, Int>;
using Change = bool;
Node merge(Node a, Node b) {
return make_pair(a.first + b.first, a.second + b.second);
}
Node e() {
return make_pair(0, 0);
}
Node apply(Change change, Node node) {
if (change) {
node.first = node.second - node.first;
}
return node;
}
Change compose(Change f, Change g) {
return f ^ g;
}
Change id() {
return false;
}
using ContributionSegTree = atcoder::lazy_segtree<
Node, merge, e, Change, apply, compose, id>;
int N;
ContributionSegTree* segtree;
void init(int _N, int M, vector<int> P, vector<int> A) {
N = _N;
vector<vector<int>> child(N);
for (int i = 1; i < N + M; ++i) {
child[P[i]].push_back(i);
}
vector<Int> contribution(M);
vector<Int> subtree(N + M, 1), subtree_left(N + M), subtree_right(N + M);
function<void (int)> compute_subtree = [&] (int u) {
if (u >= N) {
return;
}
subtree[u] = child[u].size();
for (int v : child[u]) {
compute_subtree(v);
subtree[u] *= subtree[v];
}
for (int i = 0; i < static_cast<int>(child[u].size()); ++i) {
subtree_left[child[u][i]] = subtree[child[u][i]];
if (i > 0) {
subtree_left[child[u][i]] *= subtree_left[child[u][i - 1]];
}
}
for (int i = static_cast<int>(child[u].size()) - 1; i >= 0; --i) {
subtree_right[child[u][i]] = subtree[child[u][i]];
if (i + 1 < static_cast<int>(child[u].size())) {
subtree_right[child[u][i]] *= subtree_right[child[u][i + 1]];
}
}
return;
};
compute_subtree(0);
function<void (int, Int)> compute_contribution = [&] (int u, Int current) {
if (u >= N) {
contribution[u - N] = current;
return;
}
for (int i = 0; i < static_cast<int>(child[u].size()); ++i) {
Int nxt = current;
if (i > 0) {
nxt *= subtree_left[child[u][i - 1]];
}
if (i + 1 < static_cast<int>(child[u].size())) {
nxt *= subtree_right[child[u][i + 1]];
}
compute_contribution(child[u][i], nxt);
}
};
compute_contribution(0, 1);
segtree = new ContributionSegTree(M);
for (int i = 0; i < M; ++i) {
segtree->set(i, make_pair(A[i] * contribution[i], contribution[i]));
}
}
int count_ways(int L, int R) {
segtree->apply(L - N, R - N + 1, true);
return segtree->all_prod().first.get();
}
# | 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... |