結果
| 問題 |
No.529 帰省ラッシュ
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-10-10 16:22:17 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 732 ms / 4,500 ms |
| コード長 | 8,746 bytes |
| コンパイル時間 | 2,827 ms |
| コンパイル使用メモリ | 228,984 KB |
| 最終ジャッジ日時 | 2025-01-15 06:21:45 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 18 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
struct TECC {
struct Edge {
int to, rev;
Edge() {}
Edge(int t, int r):to(t), rev(r) {}
};
int n;
vector<vector<Edge>> G;
TECC(int n_) : n(n_), G(n_) {}
void add(int u, int v) {
G[u].emplace_back(v, int(G[v].size()));
G[v].emplace_back(u, int(G[u].size())-1);
}
pair<int, vector<int>> tecc_ids() {
int now_ord = 0, group_num = 0;
vector<int> used, low(n), ord(n, -1), ids(n);
used.reserve(n);
auto dfs = [&](auto self, int v)->void {
low[v] = ord[v] = now_ord++;
used.push_back(v);
for(Edge &e:G[v]) if(e.rev != -1) {
int to = e.to;
G[to][e.rev].rev = -1;
e.rev = -1;
if(ord[to] == -1) {
self(self, to);
low[v] = min(low[v], low[to]);
}
else {
low[v] = min(low[v], ord[to]);
}
}
if(low[v] == ord[v]) {
int u;
do {
u = used.back();
used.pop_back();
ord[u] = n;
ids[u] = group_num;
} while(u != v);
group_num++;
}
};
for(int i = 0; i < n; i++) {
if(ord[i] == -1) dfs(dfs, i);
}
for(int &x:ids) {
x = group_num - 1 - x;
}
return {group_num, ids};
}
vector<vector<int>> tecc() {
pair<int, vector<int>> ids = tecc_ids();
int group_num = ids.first;
vector<int> counts(group_num);
for(int x:ids.second) counts[x]++;
vector<vector<int>> groups(group_num);
for(int i = 0; i < group_num; i++) {
groups[i].reserve(counts[i]);
}
for(int i = 0; i < n; i++) {
groups[ids.second[i]].push_back(i);
}
return groups;
}
};
struct HLD {
using Graph = vector<vector<int>>;
using F = function<void(int, int)>;
Graph G;
vector<int> parent, heavy, depth, root, ids, sub, type, inv;
int _n;
HLD() {}
HLD(int n):G(n), parent(n, -1), heavy(n, -1), depth(n), root(n, -1), ids(n), _n(n), sub(n, 1), type(n), inv(n) {}
void add(int i, int j) {
G[i].emplace_back(j);
G[j].emplace_back(i);
}
void init(vector<int> roots = vector<int>(1, 0)) {
int group = 0;
int pos = 0;
for(int rt:roots) {
dfs(rt);
bfs(rt, group++, pos);
}
}
void dfs(int rt) {
stack<pair<int, int>> st;
st.emplace(rt, 0);
while(!st.empty()) {
int v = st.top().first;
int &siz = st.top().second;
if(siz < int(G[v].size())) {
int u = G[v][siz++];
if(u == parent[v]) continue;
parent[u] = v;
depth[u] = depth[v]+1;
st.emplace(u, 0);
}
else {
st.pop();
int maxSubtree = 0;
for(int u:G[v]) {
if(u == parent[v]) continue;
sub[v] += sub[u];
if(maxSubtree < sub[u]) maxSubtree = sub[u], heavy[v] = u;
}
}
}
}
void bfs(int rt, int group, int &pos) {
queue<int> que({rt});
while(!que.empty()) {
int v = que.front();
que.pop();
for(int u = v; u != -1; u = heavy[u]) {
type[u] = group;
ids[u] = pos++;
inv[ids[u]] = u;
root[u] = v;
for(int w:G[u]) {
if(w != parent[u] and w != heavy[u]) que.emplace(w);
}
}
}
}
//edge = false -> for_each_vertex, edge = true -> for_each_edge
void for_each(int u, int v, const F &f, bool edge = false) {
assert(type[u] == type[v]);
while(true) {
if(ids[u] > ids[v]) swap(u, v);
if(root[u] == root[v]) {
if(edge) {
if(u != v) f(ids[u]+1, ids[v]+1);
}
else f(ids[u], ids[v]+1);
break;
}
f(ids[root[v]], ids[v]+1);
v = parent[root[v]];
}
}
int lca(int u, int v) {
while(true) {
if(ids[u] > ids[v]) swap(u, v);
if(root[u] == root[v]) return u;
v = parent[root[v]];
}
}
int dis(int u, int v) {
return depth[u] + depth[v] - (depth[lca(u, v)]<<1);
}
const int &operator[](int i) const {return ids[i];}
};
template<class T>
struct SegTree {
using FX = function<T(T, T)>;
int n, _n;
FX fx;
const T ex;
vector<T> dat;
SegTree(int n_, FX fx_, T ex_):fx(fx_), ex(ex_), n(1), _n(n_) {
while(n < n_) n <<= 1;
dat.assign((n<<1)-1, ex);
}
SegTree(vector<T> &v, FX fx_, T ex_):fx(fx_), ex(ex_), n(1), _n(int(v.size())) {
while(n < _n) n <<= 1;
dat.assign((n<<1)-1, ex);
copy(v.begin(), v.end(), dat.begin()+n-1);
build();
}
inline int chld(int k) {return (k<<1)+1;}
inline int chrd(int k) {return (k<<1)+2;}
void set(int i, T t) {dat[i+n-1] = t;}
void build() {
for(int k = n-2; k >= 0; k--) dat[k] = fx(dat[chld(k)], dat[chrd(k)]);
}
void update(int i, T x) {
i += n-1;
dat[i] = x;
while(i) {
i = (i-1)>>1;
dat[i] = fx(dat[chld(i)], dat[chrd(i)]);
}
}
inline T query(int a, int b) {return query(a, b, 0, 0, n);}
T query(int a, int b, int k, int l, int r) {
if(r <= a || b <= l) return ex;
if(a <= l && r <= b) return dat[k];
T vl = query(a, b, chld(k), l, (l+r)>>1);
T vr = query(a, b, chrd(k), (l+r)>>1, r);
return fx(vl, vr);
}
template<class F>
int max_right(int l, F f) {
assert(f(ex));
if(l == _n) return _n;
l += n;
T now = ex;
do {
while(~l&1) l >>= 1;
if(!f(fx(now, dat[l-1]))) {
while(l < n) {
l <<= 1;
if(f(fx(now, dat[l-1]))) {
now = fx(now, dat[l++ - 1]);
}
}
return l-n;
}
now = fx(now, dat[l++ - 1]);
} while((l & -l) != l);
return _n;
}
template<class F>
int min_left(int r, F f) {
assert(f(ex));
if(r == 0) return 0;
r += n;
T now = ex;
do {
r--;
while(r > 1 and r&1) r >>= 1;
if(!f(fx(dat[r-1], now))) {
while(r < n) {
r = chld(r);
if(f(fx(dat[r-1], now))) {
now = fx(dat[--r], now);
}
}
return r+1-n;
}
now = fx(dat[r-1], now);
} while((r & -r) != r);
return 0;
}
const T &operator[](int idx) const {return dat[idx+n-1];}
};
#undef _GLIBCXX_DEBUG
string to_string(const string &s) {return '"' + s + '"';}
string to_string(const char *s) {return to_string(string(s));}
string to_string(bool b) {return b?"true":"false";}
string to_string(vector<bool> v) {
string res = "{";
for(int i = 0; i < int(v.size()); i++) {
if(i) res += ", ";
res += to_string(v[i]);
}
res += "}";
return res;
}
template<size_t N>
string to_string(bitset<N> v) {
string res;
for(size_t i = 0; i < N; i++) res += char('0' + v[i]);
return res;
}
template<class A, class B>
string to_string(pair<A, B>);
template<class A, class B, class C>
string to_string(tuple<A, B, C>);
template<class A, class B, class C, class D>
string to_string(tuple<A, B, C, D>);
template<class A>
string to_string(A v) {
bool first = true;
string res = "{";
for(const auto &x:v) {
if(!first) res += ", ";
first = false;
res += to_string(x);
}
res += "}";
return res;
}
template<class A, class B>
string to_string(pair<A, B> p) {
return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template<class A, class B, class C>
string to_string(tuple<A, B, C> t) {
return "(" + to_string(get<0>(t)) + ", " + to_string(get<1>(t)) + ", " + to_string(get<2>(t)) + ")";
}
template<class A, class B, class C, class D>
string to_string(tuple<A, B, C, D> t) {
return "(" + to_string(get<0>(t)) + ", " + to_string(get<1>(t)) + ", " + to_string(get<2>(t)) + ", " + to_string(get<3>(t)) + ")";
}
void debug_out() {cerr << endl;}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
cerr << ' ' << to_string(H);
debug_out(T...);
}
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 822
#endif
int main() {
int n, m, q;
cin >> n >> m >> q;
TECC tecc(n);
vector<pair<int, int>> edges(m);
for(int i = 0; i < m; i++) {
int a, b;
cin >> a >> b;
tecc.add(--a, --b);
edges[i] = {a, b};
}
auto [gn, blg] = tecc.tecc_ids();
debug(blg);
debug(gn);
HLD hld(gn);
for(int i = 0; i < m; i++) {
auto [u, v] = edges[i];
if(blg[u] == blg[v]) continue;
hld.add(blg[u], blg[v]);
}
hld.init();
debug(hld.ids);
debug(hld.root);
debug(hld.parent);
SegTree<pair<int, int>> seg(gn, [](const pair<int, int> &a, const pair<int, int> &b) {return max(a, b);}, make_pair(-1, -1));
auto cor = [&](int i) {return hld[blg[i]];};
vector<priority_queue<int>> souv(gn);
while(q--) {
int type;
cin >> type;
if(type == 1) {
int u, w;
cin >> u >> w;
u = cor(u-1);
debug(u);
if(souv[u].empty() or souv[u].top() < w) seg.update(u, make_pair(w, u));
souv[u].emplace(w);
}
else {
int s, t;
cin >> s >> t;
pair<int, int> p = make_pair(-1, -1);
hld.for_each(blg[s-1], blg[t-1], [&](int i, int j)->void {p = max(p, seg.query(i, j));});
debug(p);
if(p.first == -1) {
cout << "-1\n";
}
else {
cout << p.first << '\n';
int z = p.second;
souv[z].pop();
if(souv[z].empty()) seg.update(z, make_pair(-1, -1));
else seg.update(z, make_pair(souv[z].top(), z));
}
}
}
}