結果
| 問題 |
No.1030 だんしんぐぱーりない
|
| コンテスト | |
| ユーザー |
kcvlex
|
| 提出日時 | 2020-04-17 23:56:49 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 223 ms / 2,000 ms |
| コード長 | 9,593 bytes |
| コンパイル時間 | 3,505 ms |
| コンパイル使用メモリ | 159,536 KB |
| 最終ジャッジ日時 | 2025-01-09 20:53:24 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 40 |
ソースコード
#include <limits>
#include <initializer_list>
#include <utility>
#include <bitset>
#include <tuple>
#include <type_traits>
#include <functional>
#include <string>
#include <array>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <iterator>
#include <algorithm>
#include <complex>
#include <random>
#include <numeric>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <regex>
#include <cassert>
#include <cstddef>
#define endl codeforces
#define ALL(v) std::begin(v), std::end(v)
#define ALLR(v) std::rbegin(v), std::rend(v)
using ll = std::int64_t;
using ull = std::uint64_t;
using pii = std::pair<int, int>;
using tii = std::tuple<int, int, int>;
using pll = std::pair<ll, ll>;
using tll = std::tuple<ll, ll, ll>;
template <typename T> using vec = std::vector<T>;
template <typename T> using vvec = vec<vec<T>>;
template <typename T> const T& var_min(const T &t) { return t; }
template <typename T> const T& var_max(const T &t) { return t; }
template <typename T, typename... Tail> const T& var_min(const T &t, const Tail&... tail) { return std::min(t, var_min(tail...)); }
template <typename T, typename... Tail> const T& var_max(const T &t, const Tail&... tail) { return std::max(t, var_max(tail...)); }
template <typename T, typename... Tail> void chmin(T &t, const Tail&... tail) { t = var_min(t, tail...); }
template <typename T, typename... Tail> void chmax(T &t, const Tail&... tail) { t = var_max(t, tail...); }
template <typename T> const T& clamp(const T &t, const T &low, const T &high) { return std::max(low, std::min(high, t)); }
template <typename T> void chclamp(T &t, const T &low, const T &high) { return t = clamp(t, low, high); }
template <typename T> T make_v(T init) { return init; }
template <typename T, typename... Tail> auto make_v(T init, std::size_t s, Tail... tail) { auto v = std::move(make_v(init, tail...)); return vec<decltype(v)>(s, v); }
template <typename T, std::size_t Head, std::size_t ...Tail> struct multi_dem_array { using type = std::array<typename multi_dem_array<T, Tail...>::type, Head>; };
template <typename T, std::size_t Head> struct multi_dem_array<T, Head> { using type = std::array<T, Head>; };
template <typename T, std::size_t ...Args> using mdarray = typename multi_dem_array<T, Args...>::type;
namespace init__ { struct InitIO { InitIO() { std::cin.tie(nullptr); std::ios_base::sync_with_stdio(false); std::cout << std::fixed << std::setprecision(30); } } init_io; }
namespace graph {
using Node = ll;
using Weight = ll;
using Edge = std::pair<Node, Weight>;
template <bool Directed>
struct Graph : public vvec<Edge> {
using vvec<Edge>::vvec;
void add_edge(Node f, Node t, Weight w = 1) {
(*this)[f].emplace_back(t, w);
if (!Directed) (*this)[t].emplace_back(f, w);
}
Graph<Directed> build_inv() const {
Graph<Directed> ret(this->size());
for (Node i = 0; i < this->size(); i++) {
for (const Edge &e : (*this)[i]) {
Node j;
Weight w;
std::tie(j, w) = e;
if (!Directed && j < i) continue;
ret.add_edge(j, i, w);
}
}
return ret;
}
};
template <typename Iterator>
class dst_iterator {
Iterator ite;
public:
dst_iterator(Iterator ite) : ite(ite) { }
bool operator ==(const dst_iterator<Iterator> &oth) const {
return ite == oth.ite;
}
bool operator !=(const dst_iterator<Iterator> &oth) const {
return !(*this == oth);
}
bool operator <(const dst_iterator<Iterator> &oth) const {
return ite < oth.ite;
}
bool operator >(const dst_iterator<Iterator> &oth) const {
return ite > oth.ite;
}
bool operator <=(const dst_iterator<Iterator> &oth) const {
return ite <= oth.ite;
}
bool operator >=(const dst_iterator<Iterator> &oth) const {
return ite >= oth.ite;
}
const Node& operator *() {
return ite->first;
}
const Node& operator *() const {
return ite->first;
}
dst_iterator operator ++() {
++ite;
return ite;
}
};
class dst_iteration {
using ite_type = vec<Edge>::const_iterator;
const vec<Edge> &edges;
public:
dst_iteration(const vec<Edge> &edges) : edges(edges) { }
auto begin() const {
return dst_iterator<ite_type>(edges.cbegin());
}
auto end() const {
return dst_iterator<ite_type>(edges.cend());
}
};
dst_iteration dst(const vec<Edge> &edges) {
return dst_iteration(edges);
}
}
ssize_t ceil_pow2(ssize_t s) {
ssize_t ret = 1;
while (ret <= s) ret *= 2;
return ret;
}
namespace segtree {
template <typename T>
struct SegmentTree {
using Merge = std::function<T(T, T)>;
vec<T> nodes;
Merge merge_f;
T id_ele;
SegmentTree(const vec<T> &init_v, Merge merge_f, T id_ele)
: nodes(ceil_pow2(init_v.size()) * 2 - 1, id_ele), merge_f(merge_f), id_ele(id_ele)
{
build(init_v);
}
void build(const vec<T> &v) {
if (size() < v.size()) nodes.resize(ceil_pow2(v.size()) * 2 - 1);
ssize_t s = size();
for (ssize_t i = 0; i < v.size(); i++) nodes[i + s - 1] = v[i];
for (ssize_t i = v.size(); i + s - 1 < nodes.size(); i++) nodes[i + s - 1] = id_ele;
build_parents();
}
void build_parents() {
ssize_t s = size();
for (ssize_t i = s - 2; 0 <= i; i--) nodes[i] = get_merged(i);
}
size_t size() const {
return (nodes.size() + 1) / 2;
}
const T& operator [](ll idx) const {
return nodes[idx + size() - 1];
}
T get_query(ll ql, ll qr, ll nl, ll nr, ll nidx) const {
if (nr <= ql || qr <= nl) return id_ele;
if (ql <= nl && nr <= qr) return nodes[nidx];
ll mid = (nl + nr) / 2;
ll lidx, ridx;
std::tie(lidx, ridx) = get_children_idx(nidx);
auto lv = get_query(ql, qr, nl, mid, lidx);
auto rv = get_query(ql, qr, mid, nr, ridx);
return merge_f(lv, rv);
}
T get_query(ll ql, ll qr) const {
return get_query(ql, qr, 0, size(), 0);
}
void update_query(ll idx, T val) {
idx += size() - 1;
nodes[idx] = val;
while (idx) {
ll pidx = (idx - 1) / 2;
nodes[pidx] = get_merged(pidx);
idx = pidx;
}
}
// FIXME : test
T lower_bound(ll idx, std::function<bool(T)> check, T sum) const {
if (size() - 1 <= idx) return idx - (size() - 1);
ll lidx, ridx;
std::tie(lidx, ridx) = get_children_idx(idx);
auto lv = merge_f(sum, nodes[lidx]);
if (check(lv)) return lower_bound(lidx, check, sum);
else return lower_bound(ridx, check, lv);
}
T lower_bound(std::function<bool(T)> check) const {
return lower_bound(0, check, id_ele);
}
private:
pll get_children_idx(ll idx) const {
return pll(2 * idx + 1, 2 * idx + 2);
}
T get_merged(ll idx) const {
ll a, b;
std::tie(a, b) = get_children_idx(idx);
return merge_f(nodes[a], nodes[b]);
}
};
}
const ll inf = 5e15;
struct LCA {
const graph::Graph<false> &g;
ll n;
const vec<ll> &cv;
vec<ll> ord, path, depth, max_c;
segtree::SegmentTree<pll> *segs;
segtree::SegmentTree<ll> *min_ord, *max_ord;
LCA(const graph::Graph<false> &g, const vec<ll> &cv, const vec<ll> &city)
: g(g), n(g.size()), cv(cv), ord(n), path(2 * n - 1), depth(2 * n - 1), max_c(n)
{
ll k = 0;
dfs(0, -1, -1, k, 0);
vec<pll> init_v(2 * n - 1);
for (ll i = 0; i < 2 * n - 1; i++) init_v[i] = pll(depth[i], i);
segs = new segtree::SegmentTree<pll>(init_v, [](pll a, pll b) { return std::min(a, b); }, pll(inf, inf));
min_ord = new segtree::SegmentTree<ll>(city, [&](ll a, ll b) { return get_ord(a) < get_ord(b) ? a : b; }, -1);
max_ord = new segtree::SegmentTree<ll>(city, [&](ll a, ll b) { return get_ord(a) > get_ord(b) ? a : b; }, -2);
}
ll get_ord(ll idx) {
if (idx == -1) return inf;
if (idx == -2) return -inf;
return ord[idx];
}
ll get_lca(ll l, ll r) {
ll u = ord[min_ord->get_query(l, r)];
ll v = ord[max_ord->get_query(l, r)];
return path[segs->get_query(u, v + 1).second];
}
ll get_maxc(ll l, ll r) {
return max_c[get_lca(l, r)];
}
void dfs(ll cur, ll pre, ll mc, ll &k, ll d) {
max_c[cur] = std::max(mc, cv[cur]);
ord[cur] = k;
path[k] = cur;
depth[k++] = d;
for (ll nxt : graph::dst(g[cur])) if (nxt != pre) {
dfs(nxt, cur, max_c[cur], k, d + 1);
path[k] = cur;
depth[k++] = d;
}
}
void moving(ll src, ll dst) {
min_ord->update_query(src, dst);
max_ord->update_query(src, dst);
}
};
int main() {
ll n, k, q;
std::cin >> n >> k >> q;
graph::Graph<false> g(n);
vec<ll> cv(n), av(k);
for (ll &e : cv) std::cin >> e;
for (ll &e : av) {
std::cin >> e;
e--;
}
for (ll i = 1; i < n; i++) {
ll e, f;
std::cin >> e >> f;
g.add_edge(e - 1, f - 1);
}
LCA lca(g, cv, av);
while (q--) {
ll t, x, y;
std::cin >> t >> x >> y;
x--;
if (t == 1) lca.moving(x, y - 1);
else std::cout << lca.get_maxc(x, y) << '\n';
}
return 0;
}
kcvlex