結果
| 問題 |
No.1030 だんしんぐぱーりない
|
| コンテスト | |
| ユーザー |
KoD
|
| 提出日時 | 2020-04-17 23:01:06 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 683 ms / 2,000 ms |
| コード長 | 6,232 bytes |
| コンパイル時間 | 1,425 ms |
| コンパイル使用メモリ | 83,532 KB |
| 最終ジャッジ日時 | 2025-01-09 20:37:01 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 40 |
ソースコード
#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include <numeric>
template <class T, class U>
inline bool chmin(T &lhs, const U &rhs) {
if (lhs > rhs) {
lhs = rhs;
return true;
}
return false;
}
template <class T, class U>
inline bool chmax(T &lhs, const U &rhs) {
if (lhs < rhs) {
lhs = rhs;
return true;
}
return false;
}
// [l, r) from l to r
struct range {
struct itr {
int i;
constexpr itr(int i_): i(i_) { }
constexpr void operator ++ () { ++i; }
constexpr int operator * () const { return i; }
constexpr bool operator != (itr x) const { return i != x.i; }
};
const itr l, r;
constexpr range(int l_, int r_): l(l_), r(std::max(l_, r_)) { }
constexpr itr begin() const { return l; }
constexpr itr end() const { return r; }
};
// [l, r) from r to l
struct revrange {
struct itr {
int i;
constexpr itr(int i_): i(i_) { }
constexpr void operator ++ () { --i; }
constexpr int operator * () const { return i; }
constexpr bool operator != (itr x) const { return i != x.i; }
};
const itr l, r;
constexpr revrange(int l_, int r_): l(l_ - 1), r(std::max(l_, r_) - 1) { }
constexpr itr begin() const { return r; }
constexpr itr end() const { return l; }
};
constexpr int mx = 100000;
int depth[mx];
int parent[mx][20];
std::vector<int> graph[mx];
void dfs(int u, int p) {
if (p == -1) {
depth[u] = 0;
parent[u][0] = u;
}
else {
depth[u] = depth[p] + 1;
parent[u][0] = p;
}
for (int v: graph[u]) {
if (v != p) {
dfs(v, u);
}
}
}
inline int lca(int u, int v) {
if (depth[u] > depth[v]) {
std::swap(u, v);
}
int dif = depth[v] - depth[u];
for (int j: range(0, 20)) {
if (dif & 1) {
v = parent[v][j];
}
dif >>= 1;
}
if (u == v) {
return u;
}
for (int j: revrange(0, 20)) {
if (parent[u][j] != parent[v][j]) {
u = parent[u][j];
v = parent[v][j];
}
}
return parent[u][0];
}
template <class T>
class segment_tree {
public:
using value_type = typename T::value_type;
using effector_type = typename T::effector_type;
using value_operation = typename T::value_operation;
using merge_operation = typename T::merge_operation;
private:
int size;
const value_operation op1;
const merge_operation op2;
std::vector<value_type> node;
void update() {
for (int k = size - 1; k > 0; --k) {
node[k] = op1(node[k << 1 | 0], node[k << 1 | 1]);
}
}
public:
segment_tree(): op1(value_operation()), op2(merge_operation()) { }
segment_tree(int size_, const value_type &initial_ = value_operation().identity):
op1(value_operation()), op2(merge_operation())
{ init(size_, initial_); }
segment_tree(const std::vector<value_type> &node_):
op1(value_operation()), op2(merge_operation())
{ build(node_); }
void init(int size_, const value_type &initial_ = value_operation().identity) {
size = 1;
while (size < size_) {
size <<= 1;
}
node.assign(size << 1, initial_);
update();
}
void build(const std::vector<value_type> &node_) {
init(node_.size());
assign(node_.begin(), node_.end(), 0);
}
void modify(int i, const effector_type &x) {
i += size;
node[i] = op2(node[i], x);
while (i > 1) {
i >>= 1;
node[i] = op1(node[i << 1 | 0], node[i << 1 | 1]);
}
}
template <class U>
void modify(U begin, U end, int i) {
i += size;
while (begin != end) {
node[i] = op2(node[i], *begin);
++i;
++begin;
}
update();
}
void assign(int i, const value_type &x) {
i += size;
node[i] = x;
while (i > 1) {
i >>= 1;
node[i] = op1(node[i << 1 | 0], node[i << 1 | 1]);
}
}
template <class U>
void assign(U begin, U end, int i) {
i += size;
while (begin != end) {
node[i] = *begin;
++i;
++begin;
}
update();
}
value_type operator [] (int i) const {
return node[i + size];
}
value_type fold(int l, int r) const {
l += size;
r += size;
value_type resl = op1.identity;
value_type resr = op1.identity;
while (l < r) {
if (l & 1) {
resl = op1(resl, node[l++]);
}
if (r & 1) {
resr = op1(node[--r], resr);
}
l >>= 1;
r >>= 1;
}
return op1(resl, resr);
}
};
template <class T>
struct fix_point: private T {
explicit constexpr fix_point(T &&func): T(std::forward<T>(func)) { }
template <class... Args>
constexpr decltype(auto) operator () (Args &&... args) const {
return T::operator()(*this, std::forward<Args>(args)...);
}
};
int main() {
int N, K, Q;
std::cin >> N >> K >> Q;
std::vector<int> vivace(N);
for (int &x: vivace) {
std::cin >> x;
}
std::vector<int> lives(K);
for (int &x: lives) {
std::cin >> x;
--x;
}
for (int i: range(0, N - 1)) {
int a, b;
std::cin >> a >> b;
--a; --b;
graph[a].push_back(b);
graph[b].push_back(a);
}
dfs(0, -1);
for (int j: range(0, 19)) {
for (int i: range(0, N)) {
parent[i][j + 1] = parent[parent[i][j]][j];
}
}
struct monoid {
using value_type = int;
using effector_type = int;
struct value_operation {
value_type identity = -1;
value_type operator () (const value_type &i, const value_type &j) const {
if (i == identity) return j;
if (j == identity) return i;
return lca(i, j);
}
};
struct merge_operation {
value_type operator () (const value_type &i, const effector_type &j) const {
return j;
}
};
};
segment_tree<monoid> seg(K);
for (int i: range(0, K)) {
seg.assign(i, lives[i]);
}
fix_point([&](auto yay, int u, int p) -> void {
if (p != -1) {
chmax(vivace[u], vivace[p]);
}
for (int v: graph[u]) {
if (v != p) {
yay(v, u);
}
}
})(0, -1);
while (Q--) {
int type;
std::cin >> type;
if (type == 1) {
int x, y;
std::cin >> x >> y;
--x; --y;
seg.assign(x, y);
}
else {
int l, r;
std::cin >> l >> r;
--l;
std::cout << vivace[seg.fold(l, r)] << '\n';
}
}
return 0;
}
KoD