n 個點被n−
1條邊連線成了一顆樹,邊有權值wi
。有q 個詢問,給出[a
,b]和
[c,d
] 兩個區間,表示點的標號請你求出兩個區間內各選一點之間的最大距離,即你需要求出 ma
x 1≤
n,q≤
105,1
≤wi≤
104
可以發現最長路徑具有直徑的合併性質,即兩個區間選點的最長路徑端點一定是原本兩個區間最長路徑
4 個端點中的兩個,證明和直徑性質證明相似。
所以我們可以直接用線段樹儲存區間的最長路徑端點,然後合併答案即可。 注意l
ca如果用log
2n的查詢演算法會超時,要使用rm
q−lc
a 。
時間複雜度o(
nlog
2n) 。
#include
#include
#include
#include
using namespace std;
typedef pair p;
#define mkp(a,b) make_pair(a,b)
#define ft first
#define sd second
intread()
const int n=100500;
const int m=n<<1;
const int el=n<<1;
const int lgel=18;
intlast[n],deep[n],fa[n],len[n],pos[n],high[n];
int n,q,tot,ord,lgel;
int tov[m],next[m];
int rmq[el][lgel];
int euler[el];
int getrmq(int l,int r)
int lca(int
x,int
y)int dis(int
x,int
y)p merge(p x,p y)
p merge0(p x,p y)
struct segment_tree
int mid=l+r>>1;
build(x
<<1,l,mid),build(x
<<1|1,mid+1,r);
v[x]=merge(v[x
<<1],v[x
<<1|1]);
}p query(int
x,int st,int en,int l,int r)
}t;void dfs(intx)}
void insert(int
x,int
y,int z)
void pre()
int main()
dfs(1),pre();
t.build(1,1,n);
q=read();
for (int i=1,a,b,c,d;i<=q;i++)
fclose(stdin),fclose(stdout);
return
0;}
51nod1766 樹上的最遠點對
n個點被n 1條邊連線成了一顆樹,給出a b和c d兩個區間,表示點的標號請你求出兩個區間內各選一點之間的最大距離,即你需要求出max dis i,j a i b,c j d ps 建議使用讀入優化 第一行乙個數字 n n 100000。第二行到第n行每行三個數字描述路的情況,x,y,z 1 x,y...
C 樹上的最遠點對
51nod 1766 vjudge n個點被n 1條邊連線成了一顆樹,給出 a b 和 c d 兩個區間,表示點的標號請你求出兩個區間內各選一點之間的最大距離,即你需要求出max dis i,j a i b,c j d ps 建議使用讀入優化 第一行乙個數字 n n 100000。第二行到第n行每行...
51nod 2602 樹的直徑 最遠點對
給出一顆 n 個節點的樹,求樹上最遠點對。用 d p i dp i dp i 維護以 i 為根的子樹的深度,dp i m ax d p i dp j 1 dp i max dp i dp j 1 dp i max dp i dp j 1 j 為 i 的兒子 求出任意節點 i 子樹深度之後,經過 i ...