#include <iostream>
#include <vector>
#include <set>
using namespace std;
const int N = 2e5 + 1;
const int M = 4e5 + 1;
int n, m, q, x, y;
vector <int> v[N];
int tin[N], tout[N], tim;
int arr[M][19], node[M], Log2[M];
void DFS(int s = 1, int p = -1) {
tin[s] = tout[s] = ++tim;
arr[tim][0] = tin[s];
node[tim] = s;
if (tim >= 2) Log2[tim] = Log2[tim >> 1] + 1;
for (int z: v[s]) {
if (z == p) continue;
DFS(z, s);
tout[s] = ++tim;
arr[tim][0] = tin[s];
if (tim >= 2) Log2[tim] = Log2[tim >> 1] + 1;
}
}
int LCA(int A, int B) {
int k = Log2[B - A + 1];
int Min = min(arr[A][k], arr[B - (1 << k) + 1][k]);
return node[Min];
}
int LCA2(int A, int B) {
if (tin[A] > tin[B]) swap(A, B);
int k = Log2[tout[B] - tin[A] + 1];
int Min = min(arr[tin[A]][k], arr[tout[B] - (1 << k) + 1][k]);
return node[Min];
}
int A[N];
vector <pair < pair <int, int>, int > > maybe;
bool Found;
pair <int, int> ANS;
struct SEG {
struct Node {
int Min, Max;
Node () {
Min = 1e9;
Max = -1e9;
}
Node (int Mn, int Mx) {
Min = Mn;
Max = Mx;
}
Node operator + (const Node &o) const {
return Node(min(Min, o.Min), max(Max, o.Max));
}
} st[N << 2];
void build(int l, int r, int id) {
if (l == r) {
st[id] = Node(tin[A[l]], tout[A[l]]);
return;
}
int m = (l + r) >> 1;
build(l, m, id << 1);
build(m + 1, r, id << 1 | 1);
st[id] = st[id << 1] + st[id << 1 | 1];
}
void update(int l, int r, int u, int VAL, int id) {
if (l == r) {
st[id] = Node(tin[VAL], tout[VAL]);
return;
}
int m = (l + r) >> 1;
if (u <= m) update(l, m, u, VAL, id << 1);
else update(m + 1, r, u, VAL, id << 1 | 1);
st[id] = st[id << 1] + st[id << 1 | 1];
}
void get(int l, int r, int u, int v, int par, int id) {
if (Found) return;
if (l > v || r < u) return;
if (st[id].Min > tout[par] || st[id].Max < tin[par]) return;
if (l >= u && r <= v) {
if (st[id].Min >= tin[par] && st[id].Max <= tout[par]) {
int lca = LCA(st[id].Min, st[id].Max);
maybe.push_back(pair < pair <int, int>, int >(pair <int, int>(l, r), lca));
if (lca == par) {
Found = true;
ANS = pair <int, int>(l, r);
}
return;
}
}
if (l == r) return;
int m = (l + r) >> 1;
get(l, m, u, v, par, id << 1);
get(m + 1, r, u, v, par, id << 1 | 1);
}
} seg;
int main() {
cin.tie(0); cout.tie(0);
ios_base::sync_with_stdio(false);
cin >> n >> m >> q;
for (int i = 1; i < n; ++i) {
cin >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
}
DFS();
for (int i = 1; i <= 18; ++i) {
for (int j = 1; j + (1 << i) - 1 <= tim; ++j) {
arr[j][i] = min(arr[j][i - 1], arr[j + (1 << (i - 1))][i - 1]);
}
}
for (int i = 1; i <= m; ++i) cin >> A[i];
seg.build(1, m, 1);
int t, p;
while (q--) {
cin >> t >> x >> y;
if (t == 1) {
A[x] = y;
seg.update(1, m, x, y, 1);
} else {
cin >> p;
Found = false;
maybe.clear();
seg.get(1, m, x, y, p, 1);
if (Found) {
cout << ANS.first << " " << ANS.second << "\n";
continue;
}
if (maybe.empty()) {
cout << "-1 -1\n";
} else {
int l = maybe[0].first.first, r = maybe[0].first.second;
int lca = maybe[0].second;
bool ck = true;
if (lca == p) {
cout << l << " " << r << "\n";
ck = false;
}
for (int i = 1; i < maybe.size() && ck; ++i) {
if (maybe[i].first.first == r + 1) {
r = maybe[i].first.second;
lca = LCA2(lca, maybe[i].second);
} else {
l = maybe[i].first.first;
r = maybe[i].first.second;
lca = maybe[i].second;
}
if (lca == p) {
cout << l << " " << r << "\n";
ck = false;
break;
}
}
if (ck) cout << "-1 -1\n";
}
}
}
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |