樹鏈剖分簡析

2022-02-13 17:39:56 字數 4105 閱讀 7619

落谷3384

1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include10 #include11

using

namespace

std;

12 typedef long

long

ll;13

const

double pi=acos(-1.0

);14

const

double e=exp(1

);15

//const int maxn =2e5+10;

16const ll n = 100010*4;17

18struct

node

1924

}node[n];

25ll sum[n];

26ll add[n];

2728

ll con[n];

29ll head[n];

30struct

edgeedge[n];

3536

37 ll f[n]; //

結點i的父結點

38 ll d[n]; //

結點i的深度

39 ll size[n]; //

結點i子樹的規模(結點數)

40 ll son[n]; //

結點i的重結點

41 ll top[n]; //

結點i所在鏈的頂端結點

42 ll id[n]; //

樹中結點剖分後對應的陣列下標

43 ll rk[n]; //

剖分後陣列下標對應的樹上的結點

4445 ll cnt1 = 1, cnt = 0;46

ll n,m,r,p;

4748

void

pushup(ll i)

4953

54void pushdown(ll i,ll l) //

5564}65

66void

build(ll l, ll r, ll i)

6780 ll m =node[i].mid();

8182 build(l, m, i << 1

);83 build(m+1, r, i << 1 | 1

);84

85pushup(i);86}

8788

ll query(ll l, ll r, ll i)

8994 pushdown(i, node[i].r - node[i].l + 1

);95 ll m =node[i].mid();

96 ll ans = 0;97

if(r <=m)

98101

else

102107

else

108112

}113

return

ans;

114}

115116

void

update(ll l, ll r, ll x, ll i)

117125 pushdown(i,node[i].r - node[i].l + 1

);126 ll m =node[i].mid();

127if(r <=m)

128131

else

132137

else

138142

}143

pushup(i);

144}

145146

147148

//處理size,son,f,d陣列

149void dfs1(ll u, ll fa, ll depth) //

當前節點、父節點、層次深度

150167

}168

}169

//dfs1(root, 0, 1);

//處理結點子樹的規模,每個結點的重兒子,結點所在的深度

170171

172173

//處理top,id,rk陣列

174void dfs2(ll u, ll t) //

當前結點、重鏈頂端

175

190191

}192

193void

u_xy(ll x, ll y, ll z)

194206

207 x =f[fx];

208 fx =top[x];

209}

210else

211218

219 y =f[fy];

220 fy =top[y];

221}

222}

223224

if(id[x] <=id[y])

225228

else

229232

233}

234235

ll q_xy(ll x, ll y)

236250

251 x = f[fx]; //

x更新為x鏈頭結點的父節點

252 fx = top[x]; //

fx更新為新x結點的鏈頭結點, 然後再去和fy比較,判斷x,y是否在同一條鏈上了。

253}

254else

255262

263 y =f[fy];

264 fy =top[y];

265}

266}

267268

if(id[x] <=id[y])

269272

else

273276

277return ans %p;

278}

279280

void

u_x(ll x, ll z)

281288

289ll q_x(ll x)

290293

294295

intmain()

296305

306 memset(head,-1,sizeof

(head));

307 ll cnt2 = 0

;308

for(i = 1; i < n; i++)

309320 dfs1(r, 0, 1

);321

dfs2(r, r);

322323

324 build(1, n, 1

);325

326/*

327cout << "** ";

328for(i = 1; i <= cnt; i++)

329332

cout << endl;

333*/

334while(m--)

335343

else

if(j == 2

)344

348else

if(j == 3

)349

353else

if(j == 4

)354

358}

359return0;

360}

361362

363364

365366

367368

369/*

370888888888888888888888888888 36375 68190 63528 **

371888888888888888888888888888 66907 32530 32528 **

372373

374888888888888888888888888888 36375 31713 68190 63528 **

375888888888888888888888888888 66907 86992 32530 32528 **

376377

*/

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 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 個操作,操作分為如下五種型別 換根 將乙個指定的節點設定為樹的新根。修改路徑權值 給定兩個節點,將這兩個節點間路徑上的所有節點權值 含這兩個節點 增加乙個給定的值。修改子樹權值 給定乙...