#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
#define ll long long int
const
int maxn=20000;
int t;
int n;
int dep[maxn];//儲存節點的深度
int son[maxn];//儲存節點的重兒子
int fa[maxn];//節點的父親
int sz[maxn];//以某個節點為根的子樹中節點的個數
int top[maxn];//top[v]表示節點v所在重鏈上最高的節點的編號
int indx;//用於求dfs序(嚴格來說不叫dfs序,先訪問重兒子的dfs序)時的標號
int maxn[maxn<<2];//線段樹
struct edge
; edge(int u,int v,int w,int next): u(u),v(v),w(w),next(next){}
}edge[maxn*2];
int edgecount;
int head[maxn];
void init()
inline
void add_edge(int u,int v,int w)
void dfs1(int u)//初始化dep son fa sz陣列
}void dfs2(int u,int ance)//初始化top tid陣列 ance表示重鏈的頂端節點
}///線段樹部分
inline
void pushup(int rt)
void update(int pos,int x,int l,int r,int rt)//將pos改為x
int m=(l+r)/2;
if(m>=pos)update(pos,x,l,m,rt*2);
else update(pos,x,m+1,r,rt*2+1);
pushup(rt);
}int query(int l,int r,int l,int r,int rt)//查詢區間[l,r]的最大值
int solve(int u,int v)//查詢兩個節點u v的最短路徑上的最大權值的邊
//調整成ance_u在上面
maxm=max(maxm,query(tid[ance_v],tid[v],1,indx,1));
v=fa[ance_v];
ance_v=top[v];
}if(u==v)return maxm;
if(dep[v] < dep[u])return max(maxm,query(tid[son[v]],tid[u],1,indx,1));//v在上面
else
return max(maxm,query(tid[son[u]],tid[v],1,indx,1));//u在上面
}int main()
dfs1(1);//1作為根節點開始遍歷,初始化dep,son,fa,size陣列
dfs2(1,1);
for(int i=1;iint u=edge[i].u , v=edge[i].v , w=edge[i].w;
if(dep[v] < dep[u])swap(edge[i].u,edge[i].v);//這個地方比較巧妙
update(tid[edge[i].v],w,1,indx,1);
}while(scanf("%s",op))
else
//change修改操作}}
return
0;}
專題 樹鏈剖分
樹鏈剖分 定義 size u 表示以節點u為根的子樹的節點個數 我們將乙個節點到它的兒子中size值最大的那個節點的邊定義為重邊,其他邊定義為輕邊 我們稱某條路徑為重路徑 或重鏈 當且僅當它全部由重邊組成 性質 我們可以證明對於每個點到根的路徑上都不超過o logn 條輕邊和o logn 條重路徑組...
樹鏈剖分 樹鏈剖分講解
好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 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...
樹鏈剖分 專題,學習記錄
理解了上面的那個部落格中的想法之後,你可以看這個神犇寫的 spoj上的 第一版 調了一下午 半晚上,第一次a的時候那真是excited include include include include include include using namespace std typedef long l...