题目链接 51 nod 1830 路径交
首先,理解一下题意,题目是给出一棵N个点的树,然后给出M条边,接着Q次询问,每次询问M条边中的第L条边到第R条边中有多长的边是与每条边都有交集的,记住是第L条到第R条的每一条都要交,而不是只要两两有交集就可以了。
理清楚题意之后,我们先来看一下两条边相交得到的边是哪条边?
譬如说我们有两条边。
我们想知道和
的交边长度,如图可以很清楚的看出,是
这条边,然后也可以看作是
。
我们不妨取任意两两组合形成的lca结点,那么就会有四个lca结点(因为这里求LCA次数较多,不妨使用欧拉序+RMQ的方法预处理加上
查询),为了保证相交,我们取深度最深的两个lca结点,如图:
我们选取lca1与lca2
那么,如果没有交集的时候会发生什么事情呢?
他们的四个lca会在同一个点,也就是说当没有交边的时候,他们的lca就是一个点了。
于是乎,我们利用这样的方法确定了交边的两个端点,而当线从两个求交边变成多个求共同交边的时候呢?我们可以利用已求得的交边去与交边继续交的形式,我们继续去求交边。这句话就相当于是。
这样,我们就可以用线段树来做这样的一个区间维护了。
题目中还有一处不严谨的地方就是,题目给出的并非确定根的(没说1是根结点),所以我们依然要用无向边来解决。
最后推荐交题使用C++而不是C++11,会疯狂CE。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define Big_INF 0x3f3f3f3f3f3f3f3f
#define eps 1e-6
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 5e5 + 7;
int N, M, Q, head[maxN], cnt, LOG_2[maxN << 1];
struct Eddge
{
int nex, to; ll val;
Eddge(int a=-1, int b=0, ll c=0):nex(a), to(b), val(c) {}
} edge[maxN << 1];
inline void addEddge(int u, int v, int w)
{
edge[cnt] = Eddge(head[u], v, w);
head[u] = cnt++;
}
inline void _add(int u, int v, int w) { addEddge(u, v, w); addEddge(v, u, w); }
struct Grand_Father
{
int deep[maxN], euler[maxN << 1], Esiz, rid[maxN]; ll dis[maxN];
void dfs(int u, int fa)
{
deep[u] = deep[fa] + 1; rid[u] = Esiz + 1;
for(int i=head[u], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
if(v == fa) continue;
dis[v] = dis[u] + edge[i].val;
euler[++Esiz] = u;
dfs(v, u);
}
euler[++Esiz] = u;
}
int mn[maxN << 1][22];
inline void RMQ_Init()
{
for(int i=1; i<=Esiz; i++) mn[i][0] = euler[i];
for(int j=1; (1 << j) <= Esiz; j++)
{
for(int i=1; i + (1 << j) - 1 <= Esiz; i++)
{
if(deep[mn[i][j - 1]] < deep[mn[i + (1 << (j - 1))][j - 1]]) mn[i][j] = mn[i][j - 1];
else mn[i][j] = mn[i + (1 << (j - 1))][j - 1];
}
}
}
inline int Rmq(int l, int r)
{
int det = r - l + 1, kk = LOG_2[det];
if(deep[mn[l][kk]] <= deep[mn[r - (1 << kk) + 1][kk]]) return mn[l][kk];
else return mn[r - (1 << kk) + 1][kk];
}
inline int _LCA(int u, int v)
{
int l = rid[u], r = rid[v];
if(l > r) swap(l, r);
return Rmq(l, r);
}
inline ll _Dis(int u, int v)
{
int lca = _LCA(u, v);
return dis[u] + dis[v] - 2 * dis[lca];
}
} A_lca;
inline bool cmp(int e1, int e2) { return A_lca.deep[e1] > A_lca.deep[e2]; }
pair<int, int> t[maxN];
pair<int, int> solve(pair<int, int> A, pair<int, int> B)
{
if(!A.first || !B.first) return MP(0, 0);
pair<int, int> ans;
int s[4];
s[0] = A_lca._LCA(A.first, B.first); s[1] = A_lca._LCA(A.first, B.second);
s[2] = A_lca._LCA(A.second, B.first); s[3] = A_lca._LCA(A.second, B.second);
sort(s, s + 4, cmp);
if(s[0] ^ s[1])
{
ans = MP(s[0], s[1]);
}
else ans = MP(0, 0);
return ans;
}
struct BIT_Tree
{
pair<int, int> tree[maxN << 2];
void build(int rt, int l, int r)
{
if(l == r) { tree[rt] = t[l]; return; }
int mid = HalF;
build(Lson); build(Rson);
tree[rt] = solve(tree[lsn], tree[rsn]);
}
pair<int, int> query(int rt, int l, int r, int ql, int qr)
{
if(ql <= l && qr >= r) return tree[rt];
int mid = HalF;
if(qr <= mid) return query(QL);
else if(ql > mid) return query(QR);
else return solve(query(QL), query(QR));
}
} bt;
inline void init()
{
cnt = 0;
for(int i=1; i<=N; i++) head[i] = -1;
for(int i = 1, j = 2, k = 0; i<=(N << 1); i++)
{
if(i == j) { j <<= 1; k ++; }
LOG_2[i] = k;
}
}
int main()
{
scanf("%d", &N);
init();
for(int i=1, u, v, w; i<N; i++)
{
scanf("%d%d%d", &u, &v, &w);
_add(u, v, w);
}
A_lca.dfs(1, 0);
A_lca.RMQ_Init();
scanf("%d", &M);
for(int i=1; i<=M; i++) scanf("%d%d", &t[i].first, &t[i].second);
bt.build(1, 1, M);
scanf("%d", &Q);
int L, R; pair<int, int> now;
while(Q--)
{
scanf("%d%d", &L, &R);
now = bt.query(1, 1, M, L, R);
if(now.first) printf("%lld\n", A_lca._Dis(now.first, now.second));
else printf("0\n");
}
return 0;
}