昨天的题+求LCA。(线段树写错了一个参数硬控我半个小时。。
class Solution {
struct LCA {
std::vector<int> height, euler, first, segtree;
std::vector<bool> visited;
int n;
LCA(std::vector<std::vector<int>> &g, int root = 1) {
n = g.size();
height.resize(n);
first.resize(n);
euler.reserve(n * 2);
visited.assign(n, false);
dfs(g, root);
int m = euler.size();
segtree.resize(m * 4);
build(1, 0, m - 1);
}
void dfs(std::vector<std::vector<int>> &g, int u, int h = 0) {
visited[u] = true;
height[u] = h;
first[u] = euler.size();
euler.push_back(u);
for(const auto& v: g[u]) {
if(!visited[v]) {
dfs(g,v,h + 1);
euler.push_back(u);
}
}
}
void build(int u, int tl, int tr) {
if(tl == tr) {
segtree[u] = euler[tl];
} else {
int mid = (tl + tr) >> 1;
build(u << 1, tl, mid);
build(u << 1 | 1, mid + 1, tr);
int l = segtree[u << 1],r = segtree[u << 1 | 1];
segtree[u] = (height[l] < height[r]) ? l : r;
}
}
int query(int u, int tl, int tr, int l, int r) {
if(tl > r || tr < l) {
return -1;
}
if(tl >= l && tr <= r) {
return segtree[u];
}
int mid = (tl + tr) >> 1;
int left = query(u << 1, tl, mid, l, r);
int right = query(u << 1 | 1, mid + 1, tr, l,r);
if(left == -1) return right;
if(right == -1) return left;
return height[left] < height[right] ? left : right;
}
int lca(int u, int v) {
int left = first[u], right = first[v];
if(left > right) {
swap(left,right);
}
return query(1,0,euler.size() - 1, left, right);
}
};
public:
vector<int> assignEdgeWeights(vector<vector<int>>& edges, vector<vector<int>>& queries) {
static constexpr int N = 1e5 + 10;
static constexpr int mod = 1e9 + 7;
static const std::array<int,N> pow2 = []() {
std::array<int,N> res;
res[0] = 1;
for(int i = 1; i < N; i++) {
res[i] = (res[i - 1] << 1) % mod;
}
return res;
}();
int n = edges.size() + 1;
std::vector<std::vector<int>> g(n + 1,std::vector<int>());
for(const auto&e : edges) {
int u = e[0], v = e[1];
g[u].push_back(v);
g[v].push_back(u);
}
auto solver = LCA(g);
int m = queries.size();
std::vector<int> res(m);
for(int i = 0; i < m; i++) {
int u = queries[i][0], v = queries[i][1];
int f = solver.lca(u,v);
int dis = solver.height[u] + solver.height[v] - 2 * solver.height[f];
if(dis == 0) {
res[i] = 0;
} else {
res[i] = pow2[dis - 1];
}
}
return res;
}
};