Submission #736329

#TimeUsernameProblemLanguageResultExecution timeMemory
736329puppyDigital Circuit (IOI22_circuit)C++17
100 / 100
1315 ms45496 KiB
#include "circuit.h"

#include <vector>
#include <functional>
#include <cmath>
#include <iostream>
using ll = long long;
using namespace std;
//모든 인덱스에 1씩 더하기
int par[200005];
ll tot[200005];
ll dp[200005];
vector<int> g[200005];
vector<int> prf[200005], suf[200005];
const ll mod = 1'000'002'022;
ll ans = 0;
namespace {
    int N, M;
}
//A[i]: N+1+i의 상태
struct sumseg
{
    vector<ll> tree, lazy;
    void setup(int n)
    {
        int sz = 1 << ((int)ceil(log2(n+1))+1);
        tree.resize(sz); lazy.resize(sz, 1);
    }
    int init(int s, int e, int node, vector<ll> &arr)
    {
        if (s == e) return tree[node] = arr[s];
        else return tree[node] = (init(s, (s+e)/2, 2*node, arr) + init((s+e)/2+1, e, 2*node+1, arr)) % mod;
    }
    void propagate(int s, int e, int node)
    {
        tree[node] *= lazy[node];
        if (s != e) {
            lazy[2*node] *= lazy[node];
            lazy[2*node+1] *= lazy[node];
        }
        lazy[node] = 1;
    }
    void upd(int s, int e, int node, int l, int r)
    {
        propagate(s, e, node);
        if (e < l || r < s) return;
        if (l <= s && e <= r) {
            lazy[node] *= -1;
            propagate(s, e, node);
            return;
        }
        upd(s, (s+e)/2, 2*node, l, r);
        upd((s+e)/2+1, e, 2*node+1, l, r);
        tree[node] = (tree[2*node] + tree[2*node+1]) % mod;
    }
    int query(int s, int e, int node, int l, int r)
    {
        propagate(s, e, node);
        if (e < l || r < s) return 0;
        if (l <= s && e <= r) return tree[node];
        return (query(s, (s+e)/2, 2*node, l, r) + query((s+e)/2+1, e, 2*node+1, l, r)) % mod;
    }
}seg;
void init(int N, int M, std::vector<int> P, std::vector<int> A)
{
    ::N = N;
    ::M = M;
    seg.setup(M);
    par[1] = 0;
    for (int i = 1; i < N + M; i++) {
        par[i+1] = P[i] + 1;
    }
    for (int i = 2; i <= N + M; i++) g[par[i]].push_back(i);
    function<void(int)> dfs = [&](int v)
    {
        if (v <= N) {
            tot[v] = g[v].size();
            for (int j:g[v]) {
                dfs(j);
                tot[v] = tot[v] * tot[j] % mod;
            }
        }
        else {
            tot[v] = 1;
        }
    };
    dfs(1);
    function<void(int)> dfs2 = [&](int v)
    {
        if (v > N) return;
        for (int j:g[v]) dfs2(j);
        prf[v].resize(g[v].size());
        suf[v].resize(g[v].size());
        prf[v][0] = tot[g[v][0]];
        suf[v].back() = tot[g[v].back()];
        for (int i = 1; i < (int)prf[v].size(); i++) {
            prf[v][i] = prf[v][i-1] * tot[g[v][i]] % mod;
        }
        for (int i = (int)suf[v].size() - 2; i >= 0; i--) {
            suf[v][i] = suf[v][i+1] * tot[g[v][i]] % mod;
        }
    };
    dfs2(1);
    dp[1] = 1;
    function<void(int)> dfs3 = [&](int v)
    {
        for (int j = 0; j < (int)g[v].size(); j++) {
            ll mul = 1;
            if (j >= 1) mul = mul * prf[v][j-1] % mod;
            if (j <= (int)g[v].size() - 2) mul = mul * suf[v][j+1] % mod;
            dp[g[v][j]] = dp[v] * mul % mod;
            dfs3(g[v][j]);
        }
    };
    dfs3(1);
    for (int i = N + 1; i <= N + M; i++) ans = (ans + A[i-N-1] * dp[i]) % mod;
    vector<ll> st(M);
    for (int i = N + 1; i <= N + M; i++) {
        st[i-N-1] = A[i-N-1] == 1 ? -dp[i] : dp[i];
    }
    seg.init(0, M-1, 1, st);
}

int count_ways(int L, int R) {
    int l = L - N, r = R - N;
    ans += seg.query(0, M-1, 1, l, r);
    seg.upd(0, M-1, 1, l, r);
    ans = (ans % mod + mod) % mod;
    return ans;
}
#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...