落谷3384
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include10 #include11using
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 個操作,操作分為如下五種型別 換根 將乙個指定的節點設定為樹的新根。修改路徑權值 給定兩個節點,將這兩個節點間路徑上的所有節點權值 含這兩個節點 增加乙個給定的值。修改子樹權值 給定乙...