// compile: make data
// run: time ./data < big.in > big.out && diff big.out big.ans
#include <bits/stdc++.h>
using namespace std;
// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#ifdef LOCAL
#include <debug/codeforces.h>
#define debug(x...) _debug_print(#x, x);
#define Debug(x...) _debug_print_format(#x, x);
std::ifstream terminal("/dev/tty");
#define PP cerr<<"\033[1;30mpause...\e[0m",terminal.ignore();
#else
#define debug(x...)
#define Debug(x...)
#define PP
#endif
template<typename...Args> void print_(Args...args){((cout<<args<<" "),...)<<endl;}
#define rep(i,a,b) for(int i=(a);i<(int)(b);++i)
#define sz(v) ((int)(v).size())
#define print(...) print_(__VA_ARGS__);
#define FIND(a, x) ((find(a.begin(),a.end(),(x))!=a.end())?1:0)
#define cmin(x,...) x=min({(x),__VA_ARGS__})
#define cmax(x,...) x=max({(x),__VA_ARGS__})
#define INTMAX (int)(9223372036854775807)
#define INF (int)(1152921504606846976)
#define NaN (int)(0x8b88e1d0595d51d1)
#define double long double
#define int long long
#define uint unsigned long long
#define MAXN 200010
struct DSU {
vector<int> parent, rank, s;
DSU(int n) {
parent.resize(n);
rank.resize(n);
s.resize(n, 1);
rep(i, 0, n) parent[i] = i;
}
int find(int x) {
if (parent[x] != x) parent[x] = find(parent[x]);
return parent[x];
}
void unite(int x, int y) {
int rx = find(x), ry = find(y);
if (rx == ry) return;
if (rank[rx] < rank[ry]) parent[rx] = ry, s[ry] = s[rx] + s[ry];
else if (rank[rx] > rank[ry]) parent[ry] = rx, s[rx] = s[rx] + s[ry];
else parent[ry] = rx, ++rank[rx], s[rx] = s[rx] + s[ry];
}
int get_size(int x) {
return s[find(x)];
}
};
struct Tree {
int n;
struct ed {
int v, w;
};
vector<vector<ed>> e;
struct node {
vector<node*> ch;
int wp;
node *parent = nullptr;
int depth;
};
vector<node> vertex;
vector<int> removed;
node *root;
int H = 0;
Tree(int V) {
n = V;
e.resize(n);
vertex.resize(n);
removed.resize(n);
}
void add_edge(int u, int v, int w) {
e[u].push_back({v, w}), e[v].push_back({u, w});
}
int ind(node *x) {return x - &vertex[0]; }
void setroot(int rt = 0) {
if (root != &vertex[rt]) build(rt);
root = &vertex[rt];
}
void build(int rt = 0) {
function<void(int, int)> dfs = [&](int u, int pre) {
node *x = &vertex[u];
x->depth = !~pre ? 0 : vertex[pre].depth + 1;
if (x->depth > H) H = x->depth;
x->ch.clear();
for (auto [v, w]: e[u]) {
if (v == pre || removed[v]) continue;
node *y = &vertex[v];
x->ch.push_back(y);
y->parent = x;
y->wp = w;
dfs(v, u);
}
};
dfs(rt, -1);
}
vector<vector<int>> hp, maxw;
vector<int> lg2;
void getancestor() {
lg2.resize(H+1);
rep(i, 0, H+1) lg2[i] = log2(i);
// hp.resize(n, vector<int>(lg2[H] + 1));
hp.resize(lg2[H]+1, vector<int>(n));
// maxw.resize(n, vector<int>(lg2[H] + 1, 0));
maxw.resize(lg2[H]+1, vector<int>(n, 0));
// rep(i, 0, n) hp[i][0] = vertex[i].parent ? ind(vertex[i].parent) : -1, maxw[i][0] = vertex[i].wp;
rep(i, 0, n) hp[0][i] = vertex[i].parent ? ind(vertex[i].parent) : -1, maxw[0][i] = vertex[i].wp;
rep(j, 1, lg2[H]+1) rep(i, 0, n) {
// if (~hp[i][j-1]) hp[i][j] = hp[hp[i][j-1]][j-1], maxw[i][j] = max(maxw[i][j-1], maxw[hp[i][j-1]][j-1]);
if (~hp[j-1][i]) hp[j][i] = hp[j-1][hp[j-1][i]], maxw[j][i] = max(maxw[j-1][i], maxw[j-1][hp[j-1][i]]);
// else hp[i][j] = -1, maxw[i][j] = 0;
else hp[j][i] = -1, maxw[j][i] = 0;
}
}
int lca(int u, int v) {
if (hp.empty()) getancestor();
if (vertex[u].depth < vertex[v].depth) swap(u, v);
int res = 0;
// for (int k = lg2[H]; k >= 0; --k) if (vertex[u].depth - (1<<k) >= vertex[v].depth) cmax(res, maxw[u][k]), u = hp[u][k];
for (int k = lg2[H]; k >= 0; --k) if (vertex[u].depth - (1<<k) >= vertex[v].depth) {
// debug(u, k, maxw[k][u])
cmax(res, maxw[k][u]), u = hp[k][u];
}
if (u == v) return res;
for (int k = lg2[H]; k >= 0; --k) {
// if (hp[u][k] != hp[v][k]) {
if (hp[k][u] != hp[k][v]) {
// cmax(res, maxw[u][k]), cmax(res, maxw[v][k]);
cmax(res, maxw[k][u]), cmax(res, maxw[k][v]);
// u = hp[u][k], v = hp[v][k];
u = hp[k][u], v = hp[k][v];
}
}
cmax(res, maxw[0][u], maxw[0][v]);
return res;
}
};
int32_t main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int n, m, q; cin >> n >> m >> q;
struct edge {
int u, v, w;
};
vector<edge> e;
rep(i, 0, m) {
int u, v; cin >> u >> v;
e.push_back({u-1, v-1, i+1});
}
rep(i, 0, n-1) e.push_back({i, i+1, INF});
sort(e.begin(), e.end(), [](edge a, edge b) {
return a.w < b.w;
});
DSU dsu(n);
Tree t(n);
for (auto &ed: e) {
if (dsu.find(ed.u) == dsu.find(ed.v)) continue;
t.add_edge(ed.u, ed.v, ed.w);
dsu.unite(ed.u, ed.v);
}
t.build(0);
t.getancestor();
while (q--) {
int u, v; cin >> u >> v; --u, --v;
int ans = t.lca(u, v);
if (ans == INF) ans = -1;
// else if (ans == -INF) ans = 0;
printf("%lld\n", ans);
}
return 0;
}
Yo, checked out 26superph. Seems legit for a quick spin. Nothing groundbreaking, but solid enough if you’re looking for something new. Just remember to play responsibly, eh? Check it out here: 26superph
G’day, fellas! Just had a punt on the 188bet88betapp. Pretty smooth experience, I reckon. Worth a crack if you’re keen for a bit of a flutter. Have a look: 188bet88betapp
Just cruised over to linkf8bet. It’s got a solid variety of games, might be something you are interested. Here is the link for you:linkf8bet
I love the bonuses they give to new players. It really helped me get started and build my balance. Big thanks to pkad7777 for the generosity.
Very user friendly layout and the promotions are actually worth it. I feel lucky whenever I log in here. Check out luky97login
Such a fun place to spend some free time. The game selection is huge and the rewards are actually attainable. Big shout out to bd9777game.
The slot library is absolutely massive and the visuals pop beautifully on my device. I love that they refresh the catalog often so my daily routine never gets boring. It has become my favorite little corner for winding down after work. k74slot
Had a great run today and the withdrawal was processed almost instantly. slotpixbetpaga is the real deal.