結果

問題 No.1197 モンスターショー
ユーザー Forested
提出日時 2020-11-19 19:14:15
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 495 ms / 3,000 ms
コード長 12,649 bytes
コンパイル時間 2,419 ms
コンパイル使用メモリ 212,232 KB
最終ジャッジ日時 2025-01-16 01:43:28
ジャッジサーバーID
(参考情報)
judge2 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2
other AC * 41
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

// Template
#include "bits/stdc++.h"
#define rep_override(x, y, z, name, ...) name
#define rep2(i, n) for (int i = 0; i < (int)(n); ++i)
#define rep3(i, l, r) for (int i = (int)(l); i < (int)(r); ++i)
#define rep(...) rep_override(__VA_ARGS__, rep3, rep2)(__VA_ARGS__)
#define per(i, n) for (int i = (int)(n) - 1; i >= 0; --i)
#define all(x) (x).begin(), (x).end()
using namespace std;
using ll = long long;
constexpr int inf = 1001001001;
constexpr ll INF = 3003003003003003003LL;
template <typename T>
inline bool chmin(T &x, const T &y) {
if (x > y) {
x = y;
return true;
}
return false;
}
template <typename T>
inline bool chmax(T &x, const T &y) {
if (x < y) {
x = y;
return true;
}
return false;
}
struct IOSET {
IOSET() {
cin.tie(nullptr);
ios::sync_with_stdio(false);
cout << fixed << setprecision(10);
}
} ioset;
template <typename T>
istream &operator>>(istream &is, vector<T> &vec) {
for (T &element : vec) is >> element;
return is;
}
template <typename T>
ostream &operator<<(ostream &os, vector<T> &vec) {
for (int i = 0, vec_len = (int)vec.size(); i < vec_len; ++i) {
os << vec[i] << (i + 1 == vec_len ? "" : " ");
}
return os;
}
// Two Edge Connected Components
#include <vector>
#include <stack>
template <typename G>
class TwoEdgeConnectedComponents {
const G &g;
std::stack<int> st0, st1;
std::vector<int> order;
int t;
void dfs(int v, int p) {
order[v] = t++;
st0.push(v);
st1.push(v);
bool pcnt = false;
for (int u : g[v]) {
if (order[u] == -1) {
dfs(u, v);
} else {
if (u == p && !pcnt) {
pcnt = true;
continue;
}
while (order[st1.top()] > order[u]) {
st1.pop();
}
}
}
if (st1.top() == v) {
while (true) {
int x = st0.top();
st0.pop();
comp[x] = k;
if (x == v) {
break;
}
}
++k;
st1.pop();
}
}
public:
std::vector<int> comp;
int k;
TwoEdgeConnectedComponents(const G &_g) : g(_g) {
build();
}
void build() {
int sz = g.size();
order.assign(sz, -1);
comp.assign(sz, -1);
t = 0;
k = 0;
for (int i = 0; i < sz; ++i) {
if (order[i] == -1) {
dfs(i, -1);
}
}
}
};
// Graph
#include <vector>
#include <iostream>
template <typename E>
class Graph {
std::vector<std::vector<E>> g;
public:
Graph() : g(0) {}
Graph(int n) : g(n) {}
Graph(int n, int m) : g(n) {
while (m--) {
int v;
E e;
std::cin >> v >> e;
add_edge(v, e);
}
}
int size() const {
return (int)g.size();
}
void add_edge(int from, const E &edge) {
g[from].push_back(edge);
}
const std::vector<E> &operator[](int v) const {
return g[v];
}
std::vector<E> &operator[](int v) {
return g[v];
}
};
template <typename T>
struct Wedge {
int to;
T cost;
Wedge(int _to, T _cost) : to(_to), cost(_cost) {}
operator int() const {
return to;
}
};
template <typename T>
std::istream &operator>>(std::istream &is, Wedge<T> &e) {
is >> e.to >> e.cost;
return is;
}
// Heavy-Light Decomposition
#include <vector>
#include <utility>
template <typename G>
struct HeavyLightDecomposition {
G &g;
std::vector<int> sz, par, head, in, rin, dep;
HeavyLightDecomposition(G &_g) : g(_g) {
build();
}
void build() {
sz.assign(g.size(), 0);
par.assign(g.size(), 0);
dep.assign(g.size(), 0);
dfs_size(0, -1, 0);
head.assign(g.size(), 0);
in.assign(g.size(), 0);
rin.assign(g.size(), 0);
int t = 0;
dfs_hld(0, -1, t);
}
int lca(int u, int v) {
while (true) {
if (in[u] > in[v]) {
std::swap(u, v);
}
if (head[u] == head[v]) {
return u;
}
v = par[head[v]];
}
}
template <typename T, typename F0, typename F1>
T query(int u, int v, const T &identity, const F0 &f0, const F1 &f1, bool edge) {
T _u = identity, _v = identity;
while (true) {
if (in[u] > in[v]) {
std::swap(u, v);
std::swap(_u, _v);
}
if (head[u] == head[v]) {
break;
}
_v = f1(f0(in[head[v]], in[v] + 1), _v);
v = par[head[v]];
}
return f1(f1(f0(in[u] + edge, in[v] + 1), _v), _u);
}
template <typename F>
void update(int u, int v, const F &f, bool edge) {
while (true) {
if (in[u] > in[v]) {
std::swap(u, v);
}
if (head[u] == head[v]) {
break;
}
f(in[head[v]], in[v] + 1);
v = par[head[v]];
}
f(in[u] + edge, in[v] + 1);
}
private:
void dfs_size(int v, int p, int d) {
par[v] = p;
sz[v] = 1;
dep[v] = d;
int l = g[v].size();
if (l && (int)g[v][0] == p) std::swap(g[v][0], g[v][l - 1]);
for (int i = 0; i < l; ++i) {
if ((int)g[v][i] == p) {
continue;
}
dfs_size((int)g[v][i], v, d + 1);
sz[v] += sz[(int)g[v][i]];
if (sz[(int)g[v][i]] > sz[(int)g[v][0]]) {
std::swap(g[v][0], g[v][i]);
}
}
}
void dfs_hld(int v, int p, int &t) {
in[v] = t++;
rin[in[v]] = v;
int l = g[v].size();
for (int i = 0; i < l; ++i) {
if ((int)g[v][i] == p) {
continue;
}
head[(int)g[v][i]] = (i ? (int)g[v][i] : head[v]);
dfs_hld((int)g[v][i], v, t);
}
}
};
// Lazy Segment Tree
#include <vector>
#include <cassert>
template <typename Operator>
class LazySegmentTree {
using NodeType = decltype(Operator::node_identity());
using FuncType = decltype(Operator::func_identity());
int length, height, n_;
std::vector<NodeType> node;
std::vector<FuncType> lazy;
std::vector<int> width;
void eval(int n) {
node[n] = Operator::node_func(node[n], lazy[n], width[n]);
if (n < length) {
lazy[(n << 1) | 0] = Operator::merge_func(lazy[(n << 1) | 0], lazy[n]);
lazy[(n << 1) | 1] = Operator::merge_func(lazy[(n << 1) | 1], lazy[n]);
}
lazy[n] = Operator::func_identity();
}
public:
LazySegmentTree(int n) {
assert(n >= 0);
n_ = n;
length = 1;
height = 0;
while (length < n) {
length <<= 1;
++height;
}
node.resize(length << 1, Operator::node_identity());
lazy.resize(length << 1, Operator::func_identity());
width.resize(length << 1, 1);
for (int i = length - 1; i > 0; --i) width[i] = width[i << 1] << 1;
}
LazySegmentTree(int n, NodeType x) {
assert(n >= 0);
n_ = n;
length = 1;
height = 0;
while (length < n) {
length <<= 1;
++height;
}
node.resize(length << 1, x);
for (int i = length - 1; i > 0; --i) node[i] = Operator::merge_node(node[(i << 1) | 0], node[(i << 1) | 1]);
lazy.resize(length << 1, Operator::func_identity());
width.resize(length << 1, 1);
for (int i = length - 1; i > 0; --i) width[i] = width[i << 1] << 1;
}
LazySegmentTree(std::vector<NodeType> &vec) : n_((int)vec.size()) {
length = 1;
height = 0;
while (length < (int)vec.size()) {
length <<= 1;
++height;
}
node.resize(length << 1, Operator::node_identity());
for (int i = 0; i < (int)vec.size(); ++i) node[i + length] = vec[i];
for (int i = length - 1; i > 0; --i) node[i] = Operator::merge_node(node[(i << 1) | 0], node[(i << 1) | 1]);
lazy.resize(length << 1, Operator::func_identity());
width.resize(length << 1, 1);
for (int i = length - 1; i > 0; --i) width[i] = width[i << 1] << 1;
}
void update(int a, int b, FuncType x) {
assert(a >= 0 && a <= n_ && b >= 0 && b <= n_ && a <= b);
int l = a + length, r = b + length - 1;
for (int i = height; i > 0; --i) {
eval(l >> i);
eval(r >> i);
}
++r;
while (r > l) {
if (l & 1) {
lazy[l] = Operator::merge_func(lazy[l], x);
eval(l);
++l;
}
if (r & 1) {
--r;
lazy[r] = Operator::merge_func(lazy[r], x);
eval(r);
}
l >>= 1; r >>= 1;
}
l = a + length; r = b + length - 1;
while (l >>= 1) node[l] = Operator::merge_node(Operator::node_func(node[(l << 1) | 0], lazy[(l << 1) | 0], width[(l << 1) | 0]), Operator
            ::node_func(node[(l << 1) | 1], lazy[(l << 1) | 1], width[(l << 1) | 1]));
while (r >>= 1) node[r] = Operator::merge_node(Operator::node_func(node[(r << 1) | 0], lazy[(r << 1) | 0], width[(r << 1) | 0]), Operator
            ::node_func(node[(r << 1) | 1], lazy[(r << 1) | 1], width[(r << 1) | 1]));
}
void update(int idx, NodeType x) {
assert(idx >= 0 && idx < n_);
idx += length;
for (int i = height; i >= 0; --i) eval(idx >> i);
node[idx] = x;
while (idx >>= 1) node[idx] = Operator::merge_node(Operator::node_func(node[(idx << 1) | 0], lazy[(idx << 1) | 0], width[(idx << 1) | 0]),
            Operator::node_func(node[(idx << 1) | 1], lazy[(idx << 1) | 1], width[(idx << 1) | 1]));
}
NodeType get(int a, int b) {
assert(a >= 0 && a <= n_ && b >= 0 && b <= n_ && a <= b);
int l = a + length, r = b + length - 1;
for (int i = height; i >= 0; --i) {
eval(l >> i);
eval(r >> i);
}
++r;
NodeType vl = Operator::node_identity(), vr = Operator::node_identity();
while (l < r) {
if (l & 1) {
vl = Operator::merge_node(vl, Operator::node_func(node[l], lazy[l], width[l]));
++l;
}
if (r & 1) {
--r;
vr = Operator::merge_node(Operator::node_func(node[r], lazy[r], width[r]), vr);
}
l >>= 1; r >>= 1;
}
return Operator::merge_node(vl, vr);
}
};
// Main
struct RSQ {
using NodeType = ll;
using FuncType = ll;
static NodeType node_identity() {
return 0;
}
static FuncType func_identity() {
return 0;
}
static NodeType merge_node(NodeType x, NodeType y) {
return x + y;
}
static FuncType merge_func(FuncType x, FuncType y) {
return x + y;
}
static NodeType node_func(NodeType x, FuncType y, int len) {
return x + y * len;
}
};
int main() {
int n, k, q;
cin >> n >> k >> q;
vector<int> c(k);
rep(i, k) {
cin >> c[i];
--c[i];
}
Graph<int> g(n);
rep(i, n - 1) {
int a, b;
cin >> a >> b;
--a;
--b;
g.add_edge(a, b);
g.add_edge(b, a);
}
HeavyLightDecomposition<Graph<int>> hld(g);
LazySegmentTree<RSQ> seg(n);
rep(i, k) hld.update(0, c[i], [&](int x, int y) {seg.update(x, y, 1);}, true);
ll sum = 0;
rep(i, k) sum += hld.dep[c[i]];
rep(i, q) {
int t;
cin >> t;
if (t == 1) {
int p, d;
cin >> p >> d;
--p;
--d;
hld.update(0, c[p], [&](int x, int y) {seg.update(x, y, -1);}, true);
hld.update(0, d, [&](int x, int y) {seg.update(x, y, 1);}, true);
sum -= hld.dep[c[p]];
sum += hld.dep[d];
c[p] = d;
} else {
int e;
cin >> e;
--e;
cout << sum + (ll)hld.dep[e] * k - hld.query(0, e, 0LL, [&](int x, int y) {return seg.get(x, y);}, [&](ll x, ll y) {return x + y;}, true)
                * 2 << "\n";
}
}
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0