HDU3804 樹鏈剖分 線段樹

2021-09-26 08:25:12 字數 2693 閱讀 7634

想把這一道典型題給發出來,但是無奈一直沒有找到題,直到最近才找到的。

原題鏈結

問題描述

樹上有一些有n個節點的查詢。每個查詢都被描述為兩個整數(x,y)。對於每個查詢,您應該找到集合e中邊的最大權重,它滿足以下兩個條件。

1)邊緣必須在從節點x到節點1的路徑上

.2)邊緣的權重應該小於或等於y.

現在給你樹和查詢。你能找到每個查詢的答案嗎?

輸入輸入的第一行是整數t,表示測試用例的數量。對於每種情況,第一行包含整數n表示樹中的節點數。然後是n-1行,每行包含三個整數x,y,w表示節點x和節點y之間的邊,其值為w.然後一行有乙個整數q表示查詢數。在接下來的q行中,每行包含兩個整數x和y,如上所述。

產量對於每個測試用例,您應該輸出q行。如果沒有邊滿足上述條件,則只輸出「-1」進行此查詢。否則輸出此查詢的答案。

輸入資料13

1 2 7

2 3 5

43 10

3 73 6

3 4輸出資料77

5-1

#include

#define lson k<<1,l,mid

#define rson k<<1|1,mid+1,r

using

namespace std;

const

int mx=

2e5+9;

int cnt,tot,t,n,q,u,v,w,ans[mx]

;int fa[mx]

,top[mx]

,siz[mx]

,son[mx]

,head[mx]

,de[mx]

,p[mx]

,t[mx<<2]

;struct nodeedge[mx]

,e[mx]

;bool

cmp1

(node &a,node &b)

struct nodeq[mx]

;bool

cmp2

(node &a,node &b)

void

init()

void

add(

int u,

int v,

int w)

void

dfs1

(int u,

int depth,

int father)

}return;}

void

dfs2

(int u,

int tp)

void

ins(

int k,

int l,

int r,

int pos,

int w)

int mid=

(l+r)

>>1;

if( pos<=mid )

ins(lson,pos,w)

;else

ins(rson,pos,w)

; t[k]

=max

(t[k<<1]

,t[k<<1|

1]);

}int

que(

int k,

int l,

int r,

int l,

int r)

intvs

(int u,

int v)

res=

max(res,

que(1,

1,n,p[f2]

,p[v]))

; v=fa[f2]

; f2=top[v];}

if( u==v )

return res;

if( de[v]

)// 當走出while之後,u,v一定是在同一條重鏈上,可能u==v,也可能u!=v。

swap

(u,v)

; res=

max(res,

que(1,

1,n,p[u]

,p[v]))

;return res;

}void

solve()

for(

int i=

0; i1; i++

) e[i]

=edge[i*2]

;sort

(e,e+n-

1,cmp1)

;sort

(q+1

,q+q+

1,cmp2)

;int k=0;

for(

int i=

1; i<=q ; i++

)int res=vs(

1,q[i]

.x);

// 求2節點之間的距離

if( res==0)

res=-1

; ans[q[i]

.id]

=res;

}for

(int i=

1; i<=q ; i++

)printf

("%d\n"

,ans[i]);

return;}

intmain()

dfs1(1

,1,0

);dfs2(1

,1);

solve()

;}return0;

}

hdu 3966(樹鏈剖分 線段樹)

題意 給出一棵樹,每個節點有一些敵人,有三種操作,i x,y,路徑上的所有點的人數 w。d x,y,路徑上的所有點的人數 w。q 節點x的人數。pragma comment linker,stack 1024000000,1024000000 include include include usin...

hdu 3966 樹鏈剖分 線段樹

題意 給出一棵樹,每個節點有一些敵人,有三種操作,i x,y,路徑上的所有點的人數 w。d x,y,路徑上的所有點的人數 w。q 節點x的人數。思路 如果是線性的線段樹可以做,所以要樹鏈剖分,剖分後的每條鏈是線性的,更改區間時用找公共祖先的方式,將兩點找到同一條鏈上,同一條鏈上的兩點間可以直接線段樹...

LCA 樹鏈剖分 線段樹

給出乙個 n 個節點的有根樹 編號為 0 到 n 1 根節點為 0 乙個點的深度定義為這個節點到根的距離 1 設 dep i 表示點 i 的深度,lca i,j 表示 i 與 j 的最近公共祖先。有 q 次詢問,每次詢問給出 l,r,z 求 dep lca i,z 即,求在 l,r 區間內的每個節點...