兩次dfs,第一次處理處fa,depth,size,son,第二次處理出top,rank,id
一條重鏈的編號是連續的,可以用資料結構維護,做事情的時候判斷是否在同一條鏈上,不是就把最深的跳到鏈頭的fa,然後繼續判斷
luogu3384 【模板】樹鏈剖分
區間加,求和,子樹加,求和
#include#includeview code#include
#include
#include
#include
#define ll long long
using
namespace
std;
const
int maxn=200005
;inline
intread()
while(ch>='
0'&&ch<='9')
return k*x;
}int
rt,cnt,ecnt,fir[maxn],nex[maxn],to[maxn];
intf[maxn],d[maxn],size[maxn],son[maxn],rk[maxn],top[maxn],id[maxn],val[maxn];
struct
nodea[maxn*2
];int
n,m,r,opt,x,y;
ll p,k;
void build(int u,int l,intr)}
void addd(int
u,ll v)
void pushdown(intu)}
void update(int u,int l,int
r,ll v)
}ll query(
int u,int l,int
r)void addedge(int u,int
v)void dfs1(int u,int fa,int
depth)
}void dfs2(int u,intt)}
int sum(int x,int
y)
else
fx=top[x];
fy=top[y];
}if(id[x]<=id[y]) ans+=query(1,id[x],id[y]),ans%=p;
else ans+=query(1,id[y],id[x]),ans%=p;
}void updates(int x,int y,int
c)
else
fx=top[x];
fy=top[y];
}if(id[x]<=id[y]) update(1
,id[x],id[y],c);
else update(1
,id[y],id[x],c);
}int
main()
for(int i=1;i)
cnt=0
; dfs1(r,
0,1);
dfs2(r,r);
cnt=1
; build(
1,1,n);
for(int i=1;i<=m;i++)
else
if(opt==2
)
else
if(opt==3
)
else
}return0;
}
[jloi2014]松鼠的新家
相當於n-1次+1,每次把a[i]~a[i+1]的區間+1,由於a[2]~a[n]會加兩次,所以這些還要-1
//view codeluogu-judger-enable-o2
#include#include
#include
#include
#include
#include
#define ll long long
using
namespace
std;
const
int maxn=300005
;const
int maxm=600005
;inline
intread()
while(ch>='
0'&&ch<='9')
return k*x;
}int
rt,cnt,ecnt,fir[maxn],nex[maxm],to[maxm];
intf[maxn],d[maxn],size[maxn],son[maxn],rk[maxn],top[maxn],id[maxn],val[maxn];
struct
nodea[maxm*2
];int
n,m,r,opt,x,y;
ll p,k;
void build(int u,int l,intr)}
void addd(int
u,ll v)
void pushdown(intu)}
void update(int u,int l,int
r,ll v)
}ll query(
int u,int l,int
r)void addedge(int u,int
v)void dfs1(int u,int fa,int
depth)
}void dfs2(int u,intt)}
int sum(int x,int
y)
else
fx=top[x];
fy=top[y];
}if(id[x]<=id[y]) ans+=query(1
,id[x],id[y]);
else ans+=query(1
,id[y],id[x]);
}void updates(int x,int y,int
c)
else
fx=top[x];
fy=top[y];
}if(id[x]<=id[y]) update(1
,id[x],id[y],c);
else update(1
,id[y],id[x],c);
}int
main()
dfs1(
1,0,1
); dfs2(
1,1);
build(
1,1,n);
for(int i=1;i)
for(int i=1;i<=n;i++)
return0;
}
樹鏈剖分學習
樹鏈剖分 看了學習了樹鏈剖分 適用於在樹上的路徑操作。關鍵在於重鏈的構造,把它表示到了資料結構上的連續區間,降低了複雜度。主要操作步驟實際上有三個部分 1 構造重鏈 2 如何維護資料 3 分解為輕重鏈的查詢與修改 include include include include define n 10...
樹鏈剖分學習
之前寫過樹剖的題,但沒有完全理解,現在又無法複述思路了,所以重新學習一下,部分語句參考大神的敘述 一 概念 樹鏈剖分,顧名思義,樹是由一根根樹鏈組成的,我們現在要來把它按鏈來分解掉。我們知道,大部分樹上的問題都是圍繞樹的路徑來做文章,分解成一條條的鏈之後,我們就可以對節點 邊 就行編號了,而同一根鏈...
樹鏈剖分學習
樹鏈剖分其實就是把一棵樹剖分成一條條鏈 重鏈輕鏈 然後用線段樹進行操作維護。複雜度logn 記錄 deep size fa pos bl 陣列 deep深度,size子樹節點個數,pos節點編號,bl所在重鏈頂端節點編號,fa父親編號。例題 bzoj1036 include define inf 1...