理解了上面的那個部落格中的想法之後,你可以看這個神犇寫的**~
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...