題解 P3979 遙遠的國度

2022-07-09 20:24:12 字數 2786 閱讀 4005

\[\text

\]\(\quad\)可以看看我的一篇blog關於樹鏈剖分"換根操作"筆記(內容都差不多)

\(\quad\)另外洛谷上還有一道關於換根操作的題目:cf916e jamie and tree(我的題解)

\[\text

\]換根,直接換即可

路徑修改,就和普通樹剖一樣。

子樹修改,這個需要分類討論。(下面會細講)

\]\(\quad\)因為每換一次根,樹中的很多資訊都會改變,不可能每次換根都跑兩便 \(dfs\) 預處理,所以我們考慮其他方法,對於單純的換根操作,只需要設定乙個全域性變數 \(root\) 來儲存根的編號( \(root\) 初始化為 \(1\) ,預設以 \(1\) 為根),對於其他操作,再通過分類討論 \(root\) 的位置來進行操作。

\(\quad\) 情況 \(1\) :當 \(x=root\) 時, \(x\) 就是此時整棵樹的根,那麼就是全域性修改(查詢)。

\(\quad\) 情況 \(2\) :當 \(root\) 在x子樹中時,就需要特別判斷了,根據影象我們可以發現此時x的真正子樹是包括除了 \(root\) 方向上的子樹之外其他所有節點。

\(\quad\) 對於求最小值,需要去除root這顆子樹上的範圍,所以我打了乙個特別的線段樹查詢,另外還需要乙個find操作來尋找x中root所在的兒子節點。

il int query2(int k,int l,int r,int x,int y)

il int find(int x,int y)

il int query1(int x)

if(seg[root]>=seg[x]&&seg[root]<=seg[x]+size[x]-1)

return query(1,1,n,seg[x],seg[x]+size[x]-1);

}

\(\quad\) 情況 \(3\) :其他情況下 \(x\) 的子樹以 \(root\) 為根和以 \(1\) 為根是一樣的。

\[\text

\]

#include#include#include#include#include#includeusing namespace std;

#define int long long

#define next neee

#define re register int

#define il inline

#define inf 1e18

il int read()

il void print(int x)

const int n=1e6+5;

int n,m,next[n<<1],go[n<<1],head[n],tot,a[n],top[n],root;

int sum[n<<2],seg[n],rev[n],son[n],size[n],dep[n],father[n],c[n<<2];

il void add(int x,int y)

il void dfs1(int x,int fa)

}il void dfs2(int x,int topf)

}il void build(int k,int l,int r)//建樹

int mid=l+r>>1;

build(k<<1,l,mid);build(k<<1|1,mid+1,r);

sum[k]=min(sum[k<<1],sum[k<<1|1]);

}il void add(int k,int l,int r,int v)//修改

il void pushdown(int k,int l,int r,int mid)//下傳懶標記

add(k<<1,l,mid,c[k]);add(k<<1|1,mid+1,r,c[k]);

c[k]=0;}

il void change1(int k,int l,int r,int x,int y,int z)//區間修改

int mid=l+r>>1;

if(c[k])pushdown(k,l,r,mid);

if(x<=mid)change1(k<<1,l,mid,x,y,z);

if(y>mid)change1(k<<1|1,mid+1,r,x,y,z);

sum[k]=min(sum[k<<1],sum[k<<1|1]);

}il int query(int k,int l,int r,int x,int y)//區間詢問

il int query2(int k,int l,int r,int x,int y)//特殊的區間詢問

il int find(int x,int y)//找root所在的兒子

il void change2(int x,int y,int z)//路徑修改

il int query1(int x)//子樹修改

if(seg[root]>=seg[x]&&seg[root]<=seg[x]+size[x]-1)

return query(1,1,n,seg[x],seg[x]+size[x]-1);

}signed main()

{ n=read();m=read();

for(re i=1;i\(\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 輸出除...

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

時空限制 1000ms 128mb 題目描述 zcwwzdjn在追殺十分sb的zhx,而zhx逃入了乙個遙遠的國度。當zcwwzdjn準備進入遙遠的國度繼續追殺時,守護神rapid阻攔了zcwwzdjn的去路,他需要zcwwzdjn完成任務後才能進入遙遠的國度繼續追殺。問題是這樣的 遙遠的國度有n個...