樹鏈剖分 專題,學習記錄

2021-07-05 23:57:11 字數 4649 閱讀 7533

理解了上面的那個部落格中的想法之後,你可以看這個神犇寫的**~

spoj上的

第一版~(調了一下午+半晚上,第一次a的時候那真是excited):

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int inf = 2

<< 28;

const

int size = 100100;

//-----------------------------------建邊部分-------------------------

struct edgeedges[size<<2];

int head[size],next[size],tot;

void build(int f,int t)

//-----------------------------------樹鏈部分-------------------------

//記siz[v]表示以v為根的子樹的節點數,dep[v]表示v的深度(根深度為1)

//top[v]表示v所在的鏈的頂端節點,fa[v]表示v的父親

//son[v]表示與v在同一重鏈上的v的兒子節點(姑且稱為重兒子)

int son[size],fa[size],deep[size],top[size],siz[size],w[size];

void dfs_find(int u,int faa,int dep)

}int dfs_clock;

void dfs_time(int u,int faa)

}//-----------------------------------線段樹部分-------------------------

struct treetree[size<<2];

void build(int p,int l,int r) //作用:建樹

void change(int p,int id,int w) //作用,處理max

int mid = (tree[p].l + tree[p].r) >> 1;

if(id <= mid) change(p<<1,id,w);

else change(p<<1|1,id,w);

tree[p].maxx = max(tree[p<<1].maxx,tree[p<<1|1].maxx);

}int query(int p,int l,int r) //詢問maxx 範圍l~r

int ask(int x,int y) //實際的點x,y,不是對映後的點

if(deep[x] > deep[y]) swap(x,y);

if(x != y)

return ans;

}int edg[size][3];

void init()

int n;

char in[233];

int main()

dfs_find(1,1,1);

dfs_time(1,1);

/* cout/* cout/* coutelse

}puts("");

}return

0;}

第二版:

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int inf = 2

<< 28;

const

int size = 100010;

//建邊

struct edgeedges[size<<1];

int head[size],next[size<<1],tot;

void build(int f,int t)

//鏈剖-----------------------------------//

int son[size],siz[size],deep[size],top[size],fa[size],w[size];

void dfs(int u,int faa,int dep)

}int dfs_clock;

void dfs2(int u,int faa)

}//end------------------------------------//

//線段樹部分

struct treetree[size<<2];

void build(int p,int l,int r)

void change(int p,int id,int w)

int mid = (tree[p].l + tree[p].r) >> 1;

if(id <= mid) change(p<<1,id,w); //不是 tree[p].l,因為要找id的位置,tree[p].l一定小於mid;自行腦補

else change(p<<1|1,id,w);

tree[p].maxx = max(tree[p<<1].maxx,tree[p<<1|1].maxx); //update啊別忘了!!!

}int query(int p,int l,int r)

int ask(int l,int r)

if(deep[l] > deep[r]) swap(l,r);

if(l != r)

return ans;

}int ed[size][3];

void init()

int n;

char dora[450];

int main()

dfs(1,1,1);

dfs2(1,1);

build(1,1,n);

//寫了函式不用!!!操蛋那!

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

while(233)

else

}puts("");

}return0;}

/*131 2 1

2 3 2

query 1 2

change 1 3

query 1 2

done

*/

第三版:

#include

#include

#include

#include

#include

#include

using

namespace

std;

const

int size = 100010;

const

int inf = 2

<< 28;

//建邊

struct edgeedges[size<<1];

int head[size],next[size<<1],tot;

void build(int f,int t)

//鏈剖

int top[size],son[size],siz[size],deep[size],w[size],fa[size];

void dfs(int u,int faa,int dep)

}int dfs_clock;

void dfs2(int u,int faa)

}//線段樹

struct treetree[size<<2];

void build(int p,int l,int r)

void change(int p,int id,int w)

int mid = (tree[p].l + tree[p].r) >> 1;

if(id <= mid) change(p<<1,id,w);

else change(p<<1|1,id,w);

tree[p].maxx = max(tree[p<<1].maxx,tree[p<<1|1].maxx);

}int query(int p,int l,int r)

int ask(int x,int y)

if(deep[x] > deep[y]) swap(x,y);

if(x != y)

return ans;

}//end

int ed[size][3];

void init()

int n;

char dora[450];

int main()

dfs(1,1,1);

dfs2(1,1);

build(1,1,n);

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

while(233)

else

}puts("");

}return

0;}

專題 樹鏈剖分

include include include include include include include include include include using namespace std define ll long long int const int maxn 20000 int t...

專題 樹鏈剖分

樹鏈剖分 定義 size u 表示以節點u為根的子樹的節點個數 我們將乙個節點到它的兒子中size值最大的那個節點的邊定義為重邊,其他邊定義為輕邊 我們稱某條路徑為重路徑 或重鏈 當且僅當它全部由重邊組成 性質 我們可以證明對於每個點到根的路徑上都不超過o logn 條輕邊和o logn 條重路徑組...

樹鏈剖分學習

樹鏈剖分 看了學習了樹鏈剖分 適用於在樹上的路徑操作。關鍵在於重鏈的構造,把它表示到了資料結構上的連續區間,降低了複雜度。主要操作步驟實際上有三個部分 1 構造重鏈 2 如何維護資料 3 分解為輕重鏈的查詢與修改 include include include include define n 10...