重兒子:siz[u]為v的子節點中siz值最大的,那麼u就是v的重兒子。
輕兒子:v的其它子節點。
重邊:點v與其重兒子的連邊。
輕邊:點v與其輕兒子的連邊。
重鏈:由重邊連成的路徑。
輕鏈:輕邊。
剖分後的樹有如下性質:
性質1:如果(v,u)為輕邊,則siz[u] * 2 < siz[v];
性質2:從根到某一點的路徑上輕鏈、重鏈的個數都不大於logn。
例題 : spoj 375 的**
1 #include2 #include3 #include4未完成**存檔:using
namespace
std;
5int
n,m;
6struct
node tree[100010*4];9
void built(int l,int r,int
k)10
13int mid=(l+r)/2
;14 built(l,mid,k*2);built(mid+1,r,k*2+1
);15 tree[k].sum=tree[k*2].sum+tree[k*2+1
].sum;16}
17void change(int k,int pos,int
x)18
21int mid=(l+r)/2;22
if(pos<=mid) change(k*2
,pos,x);
23if(pos>mid) change(k*2+1
,pos,x);
24 tree[k].sum=tree[k*2].sum+tree[k*2+1
].sum;25}
26int query(int k,int l,int r)//
區間查詢(以求和為例)
2730
int mid=(tree[k].l+tree[k].r)/2;31
if(l<=mid) ans+=query(k*2
,l,min(mid,r));
32if(r>mid) ans+=query(k*2+1,max(mid+1
,l),r);
33return
ans;34}
35int find(int k,int
pos)
3638
int mid=(tree[k].l+tree[k].r)/2;39
if(pos<=mid) find(k*2
,pos);
40if(pos>mid) find(k*2+1
,pos);41}
42void allchange(int k,int ls,int rs,int
x)43
46int mid=(l+r)/2;47
if(ls<=mid) allchange(k*2
,ls,min(rs,mid),x);
48if(rs>mid) allchange(k*2+1,max(ls,mid+1
),rs,x);
49}
50int main()//
線段樹 維護 區間求和 和 單點修改
51
1 #include2 #include3 #include4備註:引用自網路#define clr(a,b) memset(a,b,sizeof(a))
5using
namespace
std;
6const
int maxn=10010;7
struct
nodee[5005*4
];10
struct
tretree[maxn*4
];13
intn,pos[maxn],dep[maxn],head[maxn],m,t,p;
14int
fa[maxn],siz[maxn],son[maxn],top[maxn],nid;
15void add(int
from,int to,int
value)
19void
clear()25}
26void dfs_1(int s,int fu,int deepth)33}
34void gettop(int s,int f)42}
43void built(int l,int r,int k)
46int mid=(l+r)/2
;47 built(l,mid,k*2);built(mid+1,r,k*2+1
);48}49
void update(int k,int ps,int
val)
52int mid=(tree[k].l+tree[k].r)/2;53
if(ps<=mid) update(k*2
,ps,val);
54else update(k*2+1
,ps,val);
55 tree[k].value=max(tree[k*2].value,tree[k*2+1
].value);56}
57int query(int k,int l,int
r)58
66int find(int u,int
v)70 ans=max(ans,query(1
,pos[t1],pos[t2]));
71 u=fa[t1];t1=top[u];72}
73if(u==v) return
ans;
74if(dep[u]>dep[v]) swap(u,v);
75return max(ans,query(1,pos[u]+1
,pos[v]));76}
77int
main()78
90char s[15];int
u,v;
91while(scanf("
%s",s)==1)92
97}98return0;
99 }
樹鏈剖分 學習整理
在一棵樹上進行路徑的修改 求極值 求和 乍一看只要線段樹就能輕鬆解決,實際上,僅憑線段樹是不能搞定它的。我們需要用到一種貌似高階的複雜演算法 樹鏈剖分。樹鏈,就是樹上的路徑。剖分,就是把路徑分類為重鏈和輕鏈。重兒子 siz u 為v的子節點中siz值最大的,那麼u就是v的重兒子。輕兒子 v的其它子節...
樹鏈剖分演算法整理
樹鏈剖分可以把樹分成若干條鏈,從而維護樹上的路徑資訊。本質思想是把樹剖成可以用線性結構儲存的結構,然後可以資料結構維護。分為三種 重鏈剖分 長鏈剖分 實鏈剖分。以下以重鏈剖分為主。重鏈剖分可以將樹上的任意一條路徑劃分成不超過o l ogn o logn o logn 條連續的鏈,每條鏈上的點深度互不...
Query on a tree 樹鏈剖分整理
樹鏈剖分整理 樹鏈剖分就是把樹拆成一系列鏈,然後用資料結構對鏈進行維護。通常的剖分方法是輕重鏈剖分,所謂輕重鏈就是對於節點 u的所有子結點v,size v 最大的v與u 的邊是重邊,其它邊是輕邊,其中 size v 是以v 為根的子樹的節點個數,全部由重邊組成的路徑是重路徑,根據 上的證明,任意一點...