bzoj3083遙遠的國度 樹鏈剖分 線段樹

2021-08-07 10:25:13 字數 3201 閱讀 6115

time limit: 10 sec  

memory limit: 1280 mb

submit: 3870  

solved: 1022 [

submit][

status][

discuss]

描述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的操作,輸出一行代表對應子樹的最小點權值。

3 71 21 3

1 2 3

13 1

2 1 1 6

3 12 2 2 5

3 12 3 3 4

3 1123

4提示對於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。

zhonghaoxi提供

樹鏈剖分,由於樹鏈剖分仍然是在樹上做dfs,僅僅改變了dfs的順序,所以並不影響我們使用出棧入棧序來維護子樹區間。

具體來說,就是每個節點訪問時記錄in,回溯時記錄out,那麼詢問x子樹就變成了從in[x]到out[x]的區間上。

考錄用線段樹來維護區間最小值。修改的時候直接樹剖區間修改即可。

#include#include#include#include#include#include#include#define maxn 110000

#define maxm 220000

#define inf 2147483647

#define ls p << 1

#define rs p << 1 | 1

#define logn 21

using namespace std;

int read()

while(ch >= '0' && ch <= '9')

return x * f;}

int pre[maxn], top;

struct edge

}e[maxm];

int n, m, tot, root;

int fw[maxn], w[maxn], f[maxn][logn], d[maxn], deep[maxn], son[maxn], in[maxn], out[maxn];

struct tree

}t[maxn * 10];

void adds(int u, int v)

void dfs1(int u, int fa)}

void dfs2(int u, int chain)

if(!k) return;

dfs2(k, chain);

for(int i = pre[u]; ~i; i = e[i].next)

out[u] = tot;}

int lca(int u, int v)

if(in[u] > in[v]) swap(u, v);

return u;}

int find(int u, int d)

void update(int p)

void paint(int p, int val)

void pushdown(int p)}

void build_tree(int p, int l, int r)

int mid = l + r >> 1;

build_tree(ls, l, mid);

build_tree(rs, mid + 1, r);

update(p);}

void seg_ch(int st, int ed, int p, int val)

int mid = l + r >> 1;

pushdown(p);

if(st <= mid) seg_ch(st, min(mid, ed), ls, val);

if(ed > mid) seg_ch(max(mid + 1, st), ed, rs, val);

update(p);}

int seg_min(int st, int ed, int p)

void init()

void change(int u, int v, int val)

if(in[u] > in[v]) swap(u, v);

seg_ch(in[u], in[v], 1, val);}

int work(int p)

{ if(p == root) return seg_min(1, n, 1);

int c = lca(root, p);

if(c != p) return seg_min(in[p], out[p], 1);

else {

int v = find(root, deep[p] + 1);

//cout<

bzoj3083 遙遠的國度

題意 給定一棵樹,支援換根,路徑權值覆蓋,求子樹最小。思路 求子樹?上樹鏈剖分,但是換根怎麼辦?我們只能通過原有資訊推出換根後的答案。換根不影響路徑修改,所以只要考慮子樹最小值的維護。這裡要分3種情況討論 1 如果詢問點是當前根,直接返回整棵樹的最小值。2 如果在原樹中,當前根不在 x的子樹中,直接...

bzoj3083 遙遠的國度

time limit 10 sec memory limit 1280 mb submit 1733 solved 429 submit status discuss description 描述 zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的...

bzoj3083 遙遠的國度

time limit 10 sec memory limit 1280 mb submit 1960 solved 484 submit status discuss 描述zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神ra...