大意是一顆有根樹,根節點為1,樹上有兩個操作,乙個是對兩個節點間的節點開根號,乙個是詢問兩個節點間所有節點的權值和
開根號就是暴力對每個節點開根號(因為開根號能很快的接近1)
(樹鏈剖分解決樹上問題就是把它轉化成線性表,然後再用一些資料結構維護一下就好了。所以說線性表的的增刪查改才是重點)
ac**:
#include
using
namespace std;
#define int long long
namespace
}#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
const
int n =
1e5+5;
struct edgee[n*2]
;struct nodea[n*2]
;int n, m, cnt, head[n]
, v[n]
, rt;
int f[n]
, d[n]
, size[n]
, son[n]
, rk[n]
, top[n]
, id[n]
;void
add(
int u,
int v)
void
dfs1
(int x)}}
void
dfs2
(int x,
int tp)
}inline
void
pushup
(int x)
void
build
(int l,
int r,
int x)
int mid = l + r >>1;
a[x]
.ls = cnt++
, a[x]
.rs = cnt++
;build
(l, mid, a[x]
.ls)
;build
(mid +
1, r, a[x]
.rs)
; a[x]
.l = l,a[x]
.r = r;
pushup
(x);
}inline
len(
int x)
void
upd(
int l ,
int r,
int x)
if(a[x]
.l == a[x]
.r)int mid = a[x]
.l + a[x]
.r >>1;
if(mid >= l)
upd(l, r, a[x]
.ls);if
(mid < r)
upd(l, r, a[x]
.rs)
;pushup
(x);
}int
qry(
int l,
int r,
int x)
inline
int sum (
int x,
int y)
if(id[x]
> id[y]
)swap
(x, y)
;return ret +
qry(id[x]
, id[y]
, rt);}
void
upd(
int x,
int y)
if(id[x]
> id[y]
)swap
(x, y)
;upd
(id[x]
, id[y]
, rt);}
signed
main()
cnt =0,
dfs1(1
);dfs2(1
,1);
cnt =0,
build(1
,n,rt = cnt++);
for(
int x, y, op, i =
1; i <= m; i++
)}
HDU 6547 樹鏈剖分
wls 有三棵樹,樹上每個節點都有乙個值 aiai,現在有 2 種操作 1.將一條鏈上的所有節點的值開根號向下取整 2.求一條鏈上值的和 鏈的定義是兩點之間的最短路。input 第一行兩個數 nn,qq 分別代表樹上點的數量和運算元量。第二行 nn 個整數,第 ii 個數代表第 ii 個點的值 ai...
HDU 6547 Tree 樹鏈剖分 線段樹
hdu 6547 tree 給定一顆樹,q次操作,1 詢問樹上任意兩點之間最短路上點權和 2 將樹上任意兩點之間最短路上每個點權開根 樹上路徑問題樹鏈剖分跑不了,考慮怎樣維護區間開根,容易發現0,1開根後不改變值 開根遞減的很快,1e9開5次根後再開根就不變了,那麼就可以每次暴力更新到葉子節點,並且...
樹鏈剖分 樹鏈剖分講解
好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 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...