Submission #794616

#TimeUsernameProblemLanguageResultExecution timeMemory
794616adrilenDigital Circuit (IOI22_circuit)C++17
100 / 100
932 ms33264 KiB
#include "circuit.h"
//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using arr = array<ll, 2>;
using arrr = array<int, 3>;

constexpr ll mod = 1e9 + 2022;
constexpr int maxn = 2e5;

void fmod(ll &val)
{
    if (val >= mod) val %= mod;
}

int n, m;
basic_string <int> children[maxn];


ll subtree[maxn] = { 0 }, vals[maxn];


ll find_subtree_vals(int p)
{
    ll v = children[p].size();
    for (int i : children[p])
    {
        v *= find_subtree_vals(i);
        fmod(v);
    }
    
    subtree[p] = v;
    if (v == 0) subtree[p] = 1;
    return subtree[p];
}



void get_vals(int p)
{
    int g = children[p].size();

    vector<ll> l(g + 1, vals[p]), r(g + 1, 1);



    for (int i = 1; i <= g; i++) {
        l[i] = l[i - 1] * subtree[children[p][i - 1]]; fmod(l[i]);
    }
    
    for (int i = g - 1; i >= 0; i--) {
        r[i] = r[i + 1] * subtree[children[p][i]]; fmod(r[i]);
    }

    // cout << "P" << p << " " << vals[p] << "\n";
    // for (int i : l) cout << i << " ";
    // cout << "\n";
    // for (int i : r) cout << i << " ";
    // cout << "\n";


    for (int i = 0; i < g; i++)
    {
        vals[children[p][i]] = l[i] * r[i + 1];
        fmod(vals[children[p][i]]);
    }

    for (int i : children[p]) get_vals(i);

}

constexpr int siz = 1 << 17;

arr segtree[siz * 2] = { 0 };
bool flipped[siz * 2] = { 0 };

arr merge(arr ap, arr bp)
{
    ap[0] += bp[0], ap[1] += bp[1];
    fmod(ap[0]), fmod(ap[1]);
    return ap;
}

void print()
{
    for (int i = 1; i < 2 * siz; i++)
    {
        if (__builtin_popcount(i) == 1) cout << "\n";
        cout << segtree[i][0] << " ";
    }
    cout << endl;
}


void init(int N, int M, std::vector<int> p, std::vector<int> a) {
    n = N, m = M;


    for (int i = 1; i < n + m; i++)
    {
        children[p[i]].push_back(i);
    }

    find_subtree_vals(0);
    vals[0] = 1;
    get_vals(0);

    // for (int i = 0; i < n + m; i++) cout << subtree[i] << " ";
    // cout << "\n";
    // for (int i = 0; i < n + m; i++) cout << vals[i] << " ";
    // cout << "\n";

    for (int i = 0; i < m; i++)
    {
        segtree[i + siz][1] = vals[i + n]; // Doesn't work with modulo
        if (a[i]) segtree[i + siz][0] = segtree[i + siz][1]; 
    }

    for (int i = siz - 1; i > 0; i--)
    {
        segtree[i] = merge(segtree[i * 2], segtree[i * 2 + 1]);
    }

}

void update(int p, int sl, int sr, int gl, int gr)
{
    if (flipped[p])
    {
        segtree[p][0] = segtree[p][1] - segtree[p][0];
        if (segtree[p][0] < 0) segtree[p][0] += mod;
        

        if (p < siz) flipped[p * 2] ^= 1, flipped[p * 2 + 1] ^= 1;
        flipped[p] ^= 1;
    }

    // cout << p << " " << sl << " " << sr << " " << gl << " " << gr << " \n";

    if (gl <= sl && sr <= gr) {
        segtree[p][0] = segtree[p][1] - segtree[p][0];
        if (segtree[p][0] < 0) segtree[p][0] += mod;


        if (p < siz) flipped[p * 2] ^= 1, flipped[p * 2 + 1] ^= 1;

        return ;
    }


    if (gl > sr || sl > gr) return ;

    int mid = (sl + sr) >> 1;

    update(p * 2, sl, mid, gl, gr);
    update(p * 2 + 1, mid + 1, sr, gl, gr);

    segtree[p] = merge(segtree[p * 2], segtree[p * 2 + 1]);
}



int count_ways(int L, int R) {
    update(1, 0, siz - 1, L - n, R - n);


    return segtree[1][0];
}
#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...