Submission #964074

#TimeUsernameProblemLanguageResultExecution timeMemory
964074LucaLucaMSprinkler (JOI22_sprinkler)C++17
41 / 100
4054 ms107388 KiB
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
#include <cstring>
#include <queue>
#warning That's not AS, that's my AS

typedef long long ll;

const int NMAX = 2e5;
const int DMAX = 40;

int L;

struct Node {
  int value, lazy;
};

struct segtree {
  std::vector<Node> aint;
  std::vector<int> brute;
  int n;
  segtree() {}
  segtree(int _n) {
    n = 1;
    while (n <= _n) {
      n <<= 1;
    }
    n <<= 1;
    n |= 1;
    aint.resize(n);
    for (int i = 0; i < n; i++) {
      aint[i] = {1, 1};
    }
    n = _n;
    brute.resize(n + 1, 1);
  }

  void push(int node, int tl, int tr) {
    if (aint[node].lazy != 1) {
      aint[node].value = (ll) aint[node].value * aint[node].lazy % L;
      if (tl != tr) {
        aint[2 * node].lazy = (ll) aint[node].lazy * aint[2 * node].lazy % L;
        aint[2 * node + 1].lazy = (ll) aint[node].lazy * aint[2 * node + 1].lazy % L;
      }
      aint[node].lazy = 1;
    }
  }
  void upd(int node, int tl, int tr, int l, int r, int v) {
    assert(1 <= tl && tl <= tr && tr <= n);
    push(node, tl, tr);
    if (l <= tl && tr <= r) {
      aint[node].lazy = v;
    } else {
      int mid = (tl + tr) / 2;
      if (l <= mid) {
        upd(2 * node, tl, mid, l, r, v);
      }
      if (mid < r) {
        upd(2 * node + 1, mid + 1, tr, l, r, v);
      }
      push(2 * node, tl, mid);
      push(2 * node + 1, mid + 1, tr);
      aint[node].value = (ll) aint[2 * node].value * aint[2 * node + 1].value;
    }
  }

  int qry(int node, int tl, int tr, int p) {
    push(node, tl, tr);
    if (tl == tr) {
      return aint[node].value;
    } else {
      int mid = (tl + tr) / 2;
      if (p <= mid) {
        return qry(2 * node, tl, mid, p);
      }
      return qry(2 * node + 1, mid + 1, tr, p);
    }
  }

  void bruteUpdate(int l, int r, int v) {
    for (int i = l; i <= r; i++) {
      brute[i] = (ll) brute[i] * v % L;
    }
  }
  int bruteQuery(int p) {
    return brute[p];
  }

  void update(int l, int r, int v) {
    if (l > r) {
      return;
    }
    if (r - l <= 15) {
      bruteUpdate(l, r, v);
    } else {
      upd(1, 1, n, l, r, v);
    }
  }
  int query(int p) {
    return (ll) bruteQuery(p) * qry(1, 1, n, p) % L;
  }
};

std::vector<int> g[NMAX + 1];
int parent[NMAX + 1];
int Time[NMAX + 1];
int timer;
int lt[NMAX + 1][DMAX + 1];
int rt[NMAX + 1][DMAX + 1];

void bfs() {
  std::queue<int> q;
  q.push(1);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    Time[u] = ++timer;
    std::vector<int> newG;
    for (const auto &v : g[u]) {
      if (!Time[v]) {
        parent[v] = u;
        newG.push_back(v);
        q.push(v);
      }
    }
    g[u] = newG;
  }
}

void dfs(int u) {
  lt[u][0] = rt[u][0] = Time[u];
  for (int d = 1; d <= DMAX; d++) {
    lt[u][d] = NMAX + 1;
    rt[u][d] = 0;
  }
  for (const auto &v : g[u]) {
    assert(v != parent[u]);
    dfs(v);
    for (int d = 0; d < DMAX; d++) {
      lt[u][d + 1] = std::min(lt[u][d + 1], lt[v][d]);
      rt[u][d + 1] = std::max(rt[u][d + 1], rt[v][d]);
    }
  }
}

int main() {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(0);
  std::cout.tie(0);

  int n;
  std::cin >> n >> L;

  for (int i = 1; i < n; i++) {
    int u, v;
    std::cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
  }

  bfs();
  dfs(1);

  segtree aint(n);

  for (int i = 1; i <= n; i++) {
    int h;
    std::cin >> h;
    aint.update(Time[i], Time[i], h);
  }

  int q;
  std::cin >> q;

  while (q--) {
    int type;
    std::cin >> type;
    if (type == 1) {
      int u, d, h;
      std::cin >> u >> d >> h;
      std::vector<std::pair<int, int>> ancestors;
      int v = u;
      for (int i = 0; i <= d && v != 0; i++) {
        ancestors.push_back({v, d - i});
        v = parent[v];
      }
      std::reverse(ancestors.begin(), ancestors.end());
      int maxDepth = -1;
      for (const auto &[v, depth] : ancestors) {
        /// i + depth > maxDepth => i > maxDepth - depth
        /// i + d - depth <= d <=> i <= depth
        for (int i = std::max(0, maxDepth - depth + 1); i <= depth; i++) {
          aint.update(lt[v][i], rt[v][i], h);
          maxDepth = i + depth;
        }
      }
    } else {
      int u;
      std::cin >> u;
      std::cout << aint.query(Time[u]) << '\n';
    }
  }

  return 0;
}

Compilation message (stderr)

sprinkler.cpp:7:2: warning: #warning That's not AS, that's my AS [-Wcpp]
    7 | #warning That's not AS, that's my AS
      |  ^~~~~~~
#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...