Submission #826752

#TimeUsernameProblemLanguageResultExecution timeMemory
826752amsramanDigital Circuit (IOI22_circuit)C++17
100 / 100
920 ms31300 KiB
#include <bits/stdc++.h>

using namespace std;

template <class B>
struct LazySegTree : public B {
    using T_q = typename B::T_q;
    using T_u = typename B::T_u;
    int n, sz, log; vector<T_q> seg; vector<T_u> lazy;
    LazySegTree(int n = 0): n(n), log(__lg(max(n - 1, 1)) + 1) {
        sz = (1 << log), seg.resize(sz << 1, B::e_q), lazy.resize(sz << 1, B::e_u);
    }
    LazySegTree(vector<T_q> & init): n((int) init.size()), log(__lg(max(n - 1, 1)) + 1) {
        sz = (1 << log), seg.resize(sz << 1, B::e_q), lazy.resize(sz << 1, B::e_u);
        copy(init.begin(), init.end(), seg.begin() + sz);
        for(int i = sz - 1; i > 0; i--) refresh(i);
    }
    void refresh(int ind) {
        seg[ind] = B::comb(seg[2 * ind], seg[2 * ind + 1]);
    }
    void app(int ind, int lo, int hi, T_u delta) {
        seg[ind] = B::upd(seg[ind], delta, lo, hi);
        lazy[ind] = B::comb_upd(delta, lazy[ind]);
    }
    void push(int ind, int lo, int hi) {
        if(lo != hi) {
            int mid = (lo + hi) >> 1;
            app(2 * ind, lo, mid, lazy[ind]);
            app(2 * ind + 1, mid + 1, hi, lazy[ind]);
        }
        lazy[ind] = B::e_u;
    }
    void push_from_root(int ind) {
        ind += sz;
        for(int i = log; i > 0; i--) {
            push(ind >> i, (ind >> i << i) - sz, (((ind >> i) + 1) << i) - sz - 1);
        }
    }
    T_q qry(int lo, int hi) {
        push_from_root(lo), push_from_root(hi); T_q ret1 = B::e_q, ret2 = B::e_q;
        for(lo += sz, hi += sz; lo <= hi; lo >>= 1, hi >>= 1) {
            if(lo & 1) ret1 = B::comb(ret1, seg[lo++]);
            if(hi & 1 ^ 1) ret2 = B::comb(seg[hi--], ret2);
        }
        return B::comb(ret1, ret2);
    }
    void upd(int lo, int hi, T_u delta) {
        push_from_root(lo), push_from_root(hi); lo += sz, hi += sz;
        for(int l = lo, r = hi, lvl = 0; l <= r; l >>= 1, r >>= 1, ++lvl) {
            if(l & 1) app(l, (l << lvl) - sz, (l + 1 << lvl) - sz - 1, delta), l++;
            if(r & 1 ^ 1) app(r, (r << lvl) - sz, (r + 1 << lvl) - sz - 1, delta), r--;
        }
        for(int i = 1; i <= log; i++) {
            if(lo >> i << i != lo) refresh(lo >> i);
            if((hi + 1) >> i << i != hi + 1) refresh(hi >> i);
        }
    }
};

const int mod = 1000002022;

struct Monoid {
    using T_q = pair<int, int>; static constexpr T_q e_q = {0, 0};
    using T_u = bool; static const T_u e_u = false;
    T_q comb(T_q a, T_q b) {
        return {(a.first + b.first) % mod, (a.second + b.second) % mod};
    }
    T_q upd(T_q a, T_u b, int l, int r) {
        if(b) {
            return {(a.second - a.first + mod) % mod, a.second};
        }
        return a;
    }
    T_u comb_upd(T_u a, T_u b) {
        // a after b
        return a ^ b;
    }
};

int tot;
LazySegTree<Monoid> lst;

void init(int n, int m, vector<int> p, vector<int> a) {
    tot = n;
    vector<vector<int>> g(n);
    vector<int> prod(n + m, 1);
    vector<pair<int, int>> val(m);
    for(int i = 1; i < n + m; i++) {
        g[p[i]].push_back(i);
    }
    auto dfs = [&](auto rec, int u) -> void {
        prod[u] = (int) g[u].size();
        for(int v: g[u]) {
            if(v < n) {
                rec(rec, v);
                prod[u] = (1LL * prod[u] * prod[v]) % mod;
            }
        }
    };
    auto dfs2 = [&](auto rec, int u, int down) {
        if(u >= n) {
            val[u - n].second = down;
            return;
        }
        int sz = (int) g[u].size(), pf = 1;
        vector<int> sf;
        for(int v: g[u]) sf.push_back(prod[v]);
        sf.push_back(1);
        for(int i = sz - 1; i >= 0; i--) sf[i] = (1LL * sf[i] * sf[i + 1]) % mod;
        for(int i = 0; i < sz; i++) {
            int other = (1LL * pf * sf[i + 1]) % mod;
            rec(rec, g[u][i], (1LL * other * down) % mod);
            pf = (1LL * pf * prod[g[u][i]]) % mod;
        }
    };
    dfs(dfs, 0);
    dfs2(dfs2, 0, 1);
    for(int i = 0; i < m; i++) {
        val[i].first = a[i] * val[i].second;
    }
    lst = LazySegTree<Monoid>(val);
}

int count_ways(int l, int r) {
    lst.upd(l - tot, r - tot, true);
    return lst.seg[1].first;
}

Compilation message (stderr)

circuit.cpp: In instantiation of 'void LazySegTree<B>::upd(int, int, LazySegTree<B>::T_u) [with B = Monoid; LazySegTree<B>::T_u = bool]':
circuit.cpp:125:35:   required from here
circuit.cpp:50:50: warning: suggest parentheses around '+' inside '<<' [-Wparentheses]
   50 |             if(l & 1) app(l, (l << lvl) - sz, (l + 1 << lvl) - sz - 1, delta), l++;
      |                                                ~~^~~
circuit.cpp:51:18: warning: suggest parentheses around arithmetic in operand of '^' [-Wparentheses]
   51 |             if(r & 1 ^ 1) app(r, (r << lvl) - sz, (r + 1 << lvl) - sz - 1, delta), r--;
      |                ~~^~~
circuit.cpp:51:54: warning: suggest parentheses around '+' inside '<<' [-Wparentheses]
   51 |             if(r & 1 ^ 1) app(r, (r << lvl) - sz, (r + 1 << lvl) - sz - 1, delta), r--;
      |                                                    ~~^~~
#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...