Submission #1330119

#TimeUsernameProblemLanguageResultExecution timeMemory
1330119SpyrosAlivDigital Circuit (IOI22_circuit)C++20
100 / 100
832 ms45944 KiB
#include "circuit.h"
#include <bits/stdc++.h>
using namespace std;
#define ll long long

const ll MOD = 1000002022;
const int MN = 1e5+5;
const int BLOCK = 350;

int n, m;
vector<vector<int>> tree;
vector<ll> contrib, w, blockOn, blockOff;
vector<int> state, block, blockL, blockR;
vector<bool> blockRev;
ll ans = 0;

void calc_w(int node) {
  w[node] = tree[node].size();
  if (tree[node].empty()) w[node] = 1;
  for (auto next: tree[node]) {
    calc_w(next);
    w[node] = (w[node] * w[next]) % MOD;
  }
}

void calc_c(int node) {
  vector<int> todo;
  for (auto next: tree[node]) todo.push_back(next);
  int c = todo.size();
  if (c == 0) return;
  vector<ll> pref(c, 0), suff(c, 0);
  pref[0] = w[todo[0]];
  for (int i = 1; i < c; i++) {
    pref[i] = pref[i-1] * w[todo[i]] % MOD;
  }
  suff[c-1] = w[todo[c-1]];
  for (int i = c-2; i >= 0; i--) {
    suff[i] = suff[i+1] * w[todo[i]] % MOD;
  }
  for (int i = 0; i < c; i++) {
    contrib[todo[i]] = contrib[node];
    if (i > 0) contrib[todo[i]] = (contrib[todo[i]] * pref[i-1]) % MOD;
    if (i < c-1) contrib[todo[i]] = (contrib[todo[i]] * suff[i+1]) % MOD;
  }
  pref.clear();
  suff.clear();
  for (auto next: tree[node]) {
    calc_c(next);
  }
}

void upd(int idx) {
  if (blockR[idx] == 0) return;
  int l = blockL[idx], r = blockR[idx];
  blockOn[idx] = 0;
  blockOff[idx] = 0;
  for (int i = l; i <= r; i++) {
    if (blockRev[idx]) state[i - n] = !state[i - n];
    if (state[i - n]) {
      blockOn[idx] = (blockOn[idx] + contrib[i]) % MOD;
    }
    else {
      blockOff[idx] = (blockOff[idx] + contrib[i]) % MOD;
    }
  }
  blockRev[idx] = false;
}

void init_sqrt() {
  blockL.assign(BLOCK+1, 0);
  blockR.assign(BLOCK+1, 0);
  block.assign(n+m, 0);
  blockRev.assign(BLOCK+1, false);
  blockOn.assign(BLOCK+1, 0);
  blockOff.assign(BLOCK+1, 0);
  int curr = 0;
  for (int i = n; i < n+m; i += BLOCK) {
    blockL[curr] = i;
    for (int j = i; j < min(n+m, i + BLOCK); j++) {
      block[j] = curr;
      blockR[curr] = j;
    }
    curr++;
  }
  for (int i = 0; i < BLOCK; i++) {
    upd(i);
  }
}

void init(int N, int M, std::vector<int> P, std::vector<int> A) {
  n = N;
  m = M;
  tree.resize(n+m);
  w.assign(n+m, 0);
  contrib.assign(n+m, 0);
  for (int i = 1; i < n + m; i++) {
    tree[P[i]].push_back(i);
  }
  calc_w(0);
  contrib[0] = 1;
  calc_c(0);
  for (int i = n; i < n + m; i++) {
    //cout << "DBG: " << contrib[i] << "\n";
  }
  ans = 0;
  state = A;
  for (int i = n; i < n + m; i++) {
    if (state[i - n]) {
      ans = (ans + contrib[i]) % MOD;
    }
  }
  init_sqrt();
}

void dbg(ll x) {
  //cout << "DEBUG: " << x << "\n";
}

int count_ways(int L, int R) {
  int idxL = block[L], idxR = block[R];
  if (blockRev[idxL]) {
    ans = (ans - blockOff[idxL] + MOD) % MOD; 
  }
  else {
    ans = (ans - blockOn[idxL] + MOD) % MOD;
  }
  while (block[L] == idxL) {
    state[L - n] = !state[L - n];
    L++;
    if (L > R) break;
  }
  dbg(ans);
  upd(idxL);
  ans = (ans + blockOn[idxL]) % MOD;
  dbg(ans);
  if (L > R) return ans;
  idxL = block[L];
  if (blockRev[idxR]) {
    ans = (ans - blockOff[idxR] + MOD) % MOD; 
  }
  else {
    ans = (ans - blockOn[idxR] + MOD) % MOD;
  }
  while (block[R] == idxR) {
    state[R - n] = !state[R - n];
    R--;
    if (L > R) break;
  }
  upd(idxR);
  ans = (ans + blockOn[idxR]) % MOD;
  if (L > R) return ans;
  idxR = block[R];
  for (int i = idxL; i <= idxR; i++) {
    if (blockRev[i]) {
      ans = (ans - blockOff[i] + MOD) % MOD;
      ans = (ans + blockOn[i]) % MOD;
    }
    else {
      ans = (ans - blockOn[i] + MOD) % MOD;
      ans = (ans + blockOff[i]) % MOD;
    }
    blockRev[i] = !blockRev[i];
  }
  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...