樹剖已經是人盡皆知的sb題了嗎……
很早以前就想填掉這坑了……
考慮到樹鏈唯一,進行操作並不會對換根產生影響,那麼我們的換根操作只要記下root在**就好了
詢問的時候分類討論:
1:root == x 直接返回全樹最大值就好了
2:lca(root, x) != x,那就和x沒什麼關係了,只要返回原子樹最大值就好了
3:lca(root, x) == x,說明x在root的上方,那麼找到x的兒子中root的祖先y,除了y的子樹就都是x的子樹了
跳樹鏈和找lca可以用倍增實現
總複雜度 o(nlog2n)
code(寫的很長……):
#include usingnamespace
std;
const
int n = 1e5 + 5
;const
int lg = 20
;const
int inf = 1
<< 30
;int n, qn, a[n], tot = 0
, head[n], root;
int dfsc = 0
, id[n], siz[n], top[n];
intw[n], dep[n], fa[n][lg], son[n];
struct
edge e[n
<< 1
];inline
void add(int
from, int
to)
inline
void read(int &x)
inline
int min(int x, int
y) inline
void chkmin(int &x, int
y) inline
void swap(int &x, int &y)
void dfs1(int x, int fat, int
depth)
}void dfs2(int x, int
topf)
}inline
int getlca(int x, int
y) namespace
segt
inline
void down(int
p)
void build(int p, int l, int
r)
build(lc, l, mid);
build(rc, mid + 1
, r);
up(p);
}void modify(int p, int l, int r, int x, int y, int
v)
down(p);
if(x <=mid) modify(lc, l, mid, x, y, v);
if(y > mid) modify(rc, mid + 1
, r, x, y, v);
up(p);
}int query(int p, int l, int r, int x, int
y)
} using
namespace
segt;
inline
void mtree(int x, int y, int
v)
if(dep[x] >dep[y]) swap(x, y);
modify(
1, 1
, n, id[x], id[y], v);
}inline
int ask(int
x)
else
return query(1, 1, n, id[x], id[x] + siz[x] - 1);}
intmain()
dfs1(
1, 0, 1
);
for(int i = 1; i <= n; i++) read(a[i]);
dfs2(
1, 1
); build(
1, 1
, n);
read(root);
for(int op; qn--; )
if(op == 3
) }
return0;
}
題解 P3979 遙遠的國度
text quad 可以看看我的一篇blog關於樹鏈剖分 換根操作 筆記 內容都差不多 quad 另外洛谷上還有一道關於換根操作的題目 cf916e jamie and tree 我的題解 text 換根,直接換即可 路徑修改,就和普通樹剖一樣。子樹修改,這個需要分類討論。下面會細講 quad 因為...
洛谷 P3979 遙遠的國度
洛谷傳送門 zcwwzdjn在追殺zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神rapid阻攔了zcwwzdjn的去路,他需要zcwwzdjn完成任務後才能進入遙遠的國度繼續追殺。問題是這樣的 遙遠的國度有 nn 個城市,這些城市之間由一些路連線且這些城...
P3979 遙遠的國度 樹鏈剖分
題意 操作一 將根節點變為x 操作二 將x到y的點權變為v 操作三 詢問x及其子樹中最小點權 按照1進行樹剖即可 如果 x為根節點 那麼輸出線段樹最小值即可 如果x不在1 root的路徑上 那麼正常輸出x的子樹即可 為 siz 如果x在1 root的路徑上 設x在1 root上的兒子節點為y 輸出除...