洛谷P3979 遙遠的國度 樹鏈剖分

2021-09-16 12:06:32 字數 3696 閱讀 9661

時空限制 1000ms / 128mb

題目描述

zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神rapid阻攔了zcwwzdjn的去路,他需要zcwwzdjn完成任務後才能進入遙遠的國度繼續追殺。

問題是這樣的:遙遠的國度有n個城市,這些城市之間由一些路連線且這些城市構成了一顆樹。這個國度有乙個首都,我們可以把這個首都看做整棵樹的根,但遙遠的國度比較奇怪,首都是隨時有可能變為另外乙個城市的。遙遠的國度的每個城市有乙個防禦值,有些時候rapid會使得某兩個城市之間的路徑上的所有城市的防禦值都變為某個值。

rapid想知道在某個時候,如果把首都看做整棵樹的根的話,那麼以某個城市為根的子樹的所有城市的防禦值最小是多少。

由於rapid無法解決這個問題,所以他攔住了zcwwzdjn希望他能幫忙。但zcwwzdjn還要追殺sb的zhx,所以這個重大的問題就被轉交到了你的手上。

輸入格式:

第1行兩個整數n m,代表城市個數和運算元。

第2行至第n行,每行兩個整數 u v,代表城市u和城市v之間有一條路。

第n+1行,有n個整數,代表所有點的初始防禦值。

第n+2行乙個整數 id,代表初始的首都為id。

第n+3行至第n+m+2行,首先有乙個整數opt,如果opt=1,接下來有乙個整數id,代表把首都修改為id;如果opt=2,接下來有三個整數p1 p2 v,代表將p1 p2路徑上的所有城市的防禦值修改為v;如果opt=3,接下來有乙個整數 id,代表詢問以城市id為根的子樹中的最小防禦值。

輸出格式:

對於每個opt=3的操作,輸出一行代表對應子樹的最小點權值。

說明對於20%的資料,n<=1000 m<=1000。

對於另外10%的資料,n<=100000,m<=100000,保證修改為單點修改。

對於另外10%的資料,n<=100000,m<=100000,保證樹為一條鏈。

對於另外10%的資料,n<=100000,m<=100000,沒有修改首都的操作。

對於100%的資料,n<=100000,m<=100000,0《所有權值<=2^31

題目分析

首先路徑修改與根無關,所以直接按套路操作

假設一開始樹剖的根為1,當前根為rt,詢問點為u

1.若u==rt,u得子樹就是整棵樹

2.若lca(u,rt)!=u,則u的子樹不變

3.若lca(u,rt)==u,則u的子樹(以rt為根)為整棵樹 - rt的祖先中u的兒子的子樹(以1為根)

#include

#include

#include

#include

#include

#include

#include

using

namespace std;

typedef

long

long lt;

typedef

double dd;

lt read()

while

(ss>=

'0'&&ss<=

'9')

return f*x;

}const lt inf=

1e10

;const

int maxn=

200010

;int n,m,rt;

lt a[maxn]

;struct nodee[maxn<<1]

;int head[maxn]

,tot;

int top[maxn]

,son[maxn]

,fa[maxn]

,size[maxn]

;int dep[maxn]

,num[maxn]

,pos[maxn]

,cnt;

lt mi[maxn<<2]

,sett[maxn<<2]

;void

add(

int u,

int v)

void

dfs1

(int u,

int pa)

}void

dfs2

(int u,

int tp)

}void

build

(int s,

int t,

int p)

int mid=s+t>>1;

build

(s,mid,p<<1)

;build

(mid+

1,t,p<<1|

1); mi[p]

=min

(mi[p<<1]

,mi[p<<1|

1]);

}void

push

(int p)

void

update

(int ll,

int rr,

int s,

int t,

int p,lt val)

int mid=s+t>>1;

push

(p);

if(ll<=mid)

update

(ll,rr,s,mid,p<<

1,val);if

(rr>mid)

update

(ll,rr,mid+

1,t,p<<1|

1,val)

; mi[p]

=min

(mi[p<<1]

,mi[p<<1|

1]);

}void

modify

(int u,

int v,lt val)

if(dep[u]

>dep[v]

)swap

(u,v)

;update

(num[u]

,num[v],1

,n,1

,val);}

lt qmin

(int ll,

int rr,

int s,

int t,

int p)

intlca

(int u,

int v)

return dep[u]

?u:v;

}int

find

(int u,

int v)

return son[u];}

intquery

(int u)

else

return

qmin

(num[u]

,num[u]

+size[u]-1

,1,n,1);

}int

main()

for(

int i=

1;i<=n;

++i) a[i]

=read()

; rt=

read()

;

dep[1]

=1;dfs1(1

,0);

dfs2(1

,1);

build(1

,n,1);

while

(m--

)else

if(opt==3)

}return0;

}

P3979 遙遠的國度 樹鏈剖分

題意 操作一 將根節點變為x 操作二 將x到y的點權變為v 操作三 詢問x及其子樹中最小點權 按照1進行樹剖即可 如果 x為根節點 那麼輸出線段樹最小值即可 如果x不在1 root的路徑上 那麼正常輸出x的子樹即可 為 siz 如果x在1 root的路徑上 設x在1 root上的兒子節點為y 輸出除...

洛谷 P3979 遙遠的國度

洛谷傳送門 zcwwzdjn在追殺zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神rapid阻攔了zcwwzdjn的去路,他需要zcwwzdjn完成任務後才能進入遙遠的國度繼續追殺。問題是這樣的 遙遠的國度有 nn 個城市,這些城市之間由一些路連線且這些城...

題解 P3979 遙遠的國度

text quad 可以看看我的一篇blog關於樹鏈剖分 換根操作 筆記 內容都差不多 quad 另外洛谷上還有一道關於換根操作的題目 cf916e jamie and tree 我的題解 text 換根,直接換即可 路徑修改,就和普通樹剖一樣。子樹修改,這個需要分類討論。下面會細講 quad 因為...