樹鏈剖分 (ZQU1607)

2022-06-02 08:06:07 字數 3559 閱讀 5757

這道題與模板之間,多了個確定哪個為根的操作;

這道題有技巧,並不需要真正去建立以某個節點為根的樹

關於路徑的操作,無論以哪個點為根,得出的答案無影響;

關於對子節點進行操作的,有幾種情況,

當查詢節點剛好是根節點的話,就直接從1開始遍歷就好 (因為這道題是以1為根節點)

當查詢的節點的孩子或孫子中包括根節點的話,則需要用根節點得出的值去剪掉這個根節點得出的值 

(這裡以查詢作為例子,更新值也是同樣的道理)

所以,整個**中跟模板的區別是,多了一步 確定查詢節點跟根節點關係的** (**中的函式名為work2)

1 #include2 #include3 #include4 #include5 #include6

#define rint register int

7#define mem(a,b) memset(a,(b),sizeof(a))

8#define temp template9

using

namespace

std;

10 typedef long

long

ll;11

12#define mid ((l+r)>>1)

13#define lson rt<<1,l,mid

14#define rson rt<<1|1,mid+1,r

15#define len (r-l+1)

16 ll root,n; //

n需要作為全域性變數

17const ll maxn=200000+10;18

//見題意

19ll e,beg[maxn],nex[maxn],to[maxn],w[maxn],wt[maxn];

20//

鏈式前向星陣列,w、wt初始點權陣列

21 ll a[maxn<<2],laz[maxn<<2

];22

//線段樹陣列、lazy操作

23ll son[maxn],id[maxn],fa[maxn],cnt,dep[maxn],siz[maxn],top[maxn];

24//

son重兒子編號,id新編號,fa父親節點,cnt dfs_clock/dfs序,dep深度,siz子樹大小,top當前鏈頂端節點

25 ll res=0;26

//查詢答案

2728 inline void add(ll x,ll y)

33//

-------------------------------------- 以下為線段樹

34 inline void

pushdown(ll rt,ll lenn)

4344 inline void

build(ll rt,ll l,ll r)

50build(lson);

51build(rson);

52 a[rt]=a[rt<<1]+a[rt<<1|1

];53}54

55 inline void

query(ll rt,ll l,ll r,ll l,ll r)

57else62}

6364 inline void

update(ll rt,ll l,ll r,ll l,ll r,ll k)

69else75}

76//

---------------------------------以上為線段樹

77inline ll qrange(ll x,ll y)

87//

直到兩個點處於一條鏈上

88if(dep[x]>dep[y])swap(x,y);//

把x點深度更深的那個點

89 res=0

;90 query(1,1,n,id[x],id[y]);//

這時再加上此時兩個點的區間和即可

91 ans+=res;

92return

ans;93}

9495 inline void updrange(ll x,ll y,ll k)

102if(dep[x]>dep[y])swap(x,y);

103 update(1,1

,n,id[x],id[y],k);

104}

105106

inline ll qson(ll x)

111112 inline void updson(ll x,ll k)

115116 inline void dfs1(ll x,ll f,ll deep)

128}

129130 inline void dfs2(ll x,ll topf)

141}

142ll check2(ll xx,ll yy)

148if(dep[xx]>dep[yy]) swap(xx,yy);

149if(xx!=rt) return

0; //

如果得出的點不是等於查詢節點

150//

則說明沒有關係,這裡舉個例子,比如在乙個樹中,他的父親節點是根節點,

151//

那麼就沒有關係;換乙個說法(如果yy不是xx的子樹,則沒有影響)

152//

兩個節點沒有關係,return 0

153if(fa[lst]==xx) return lst; //

如果lst的父親是這個查詢節點,則根節點

154//

便是這個lst;

155return son[xx]; //

可以說return son[xx]是最難理解的了。

156 } //

不過還是理解了,開心! 如果fa[lst]的節點是查詢節點的子節點或者孫節點;

157//

那麼從他重兒子以下的點都是不在查詢範圍(更新範圍)的,這裡畫圖模擬一遍

158//

就會發現就是這麼個道理。

159int

main()

160168

ll m;

169 scanf("

%lld

",&m);

170 dfs1(1,0,1

);171 dfs2(1,1

);172 build(1,1

,n);

173 root=1

;174

while(m--)

180if(k==2

)184

if(k==3

)187 y=check2(x,root);

188if(y==0

) updson(x,z);

189else

193}

194if(k==4

)198

if(k==5

)204 y=check2(x,root);

205if(y==0) printf("

%lld\n

",qson(x));

206else

209}

210}

211return0;

212 }

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...

演算法入門 樹鏈剖分 輕重鏈剖分

目錄 3.0 求 lca 4.0 利用資料結構維護資訊 5.0 例題 參考資料 資料結構入門 線段樹 發表於 2019 11 28 20 39 dfkuaid 摘要 線段樹的基本 建樹 區間查詢 單點修改 及高階操作 區間修改 單點查詢 區間修改 區間查詢 標記下傳 標記永久化 閱讀全文 樹鏈剖分用...

樹鏈剖分 樹剖換根

這是一道模板題。給定一棵 n 個節點的樹,初始時該樹的根為 1 號節點,每個節點有乙個給定的權值。下面依次進行 m 個操作,操作分為如下五種型別 換根 將乙個指定的節點設定為樹的新根。修改路徑權值 給定兩個節點,將這兩個節點間路徑上的所有節點權值 含這兩個節點 增加乙個給定的值。修改子樹權值 給定乙...