51NOD 1766 樹上的最遠點對

2021-07-14 05:48:34 字數 1595 閱讀 1287

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 ...