入口
題目描述
如題,已知一棵包含 nn 個結點的樹(連通且無環),每個節點上包含乙個數值,需要支援以下操作:
操作 11: 格式: 1\ x\ y\ z1 x y z 表示將樹從 xx 到 yy 結點最短路徑上所有節點的值都加上 zz。
操作 22: 格式: 2\ x\ y2 x y 表示求樹從 xx 到 yy 結點最短路徑上所有節點的值之和。
操作 33: 格式: 3\ x\ z3 x z 表示將以 xx 為根節點的子樹內所有節點值都加上 zz。
操作 44: 格式: 4\ x4 x 表示求以 xx 為根節點的子樹內所有節點值之和
輸入格式
第一行包含 44 個正整數 n,m,r,pn,m,r,p,分別表示樹的結點個數、操作個數、根節點序號和取模數(即所有的輸出結果均對此取模)。
接下來一行包含 nn 個非負整數,分別依次表示各個節點上初始的數值。
接下來 n-1n−1 行每行包含兩個整數 x,yx,y,表示點 xx 和點 yy 之間連有一條邊(保證無環且連通)。
接下來 mm 行每行包含若干個正整數,每行表示乙個操作,格式如下:
操作 11: 1\ x\ y\ z1 x y z;
操作 22: 2\ x\ y2 x y;
操作 33: 3\ x\ z3 x z;
操作 44: 4\ x4 x。
輸出格式
輸出包含若干行,分別依次表示每個操作 22 或操作 44 所得的結果(對 pp 取模)。
輸入輸出樣例
輸入 #1複製
5 5 2 24
7 3 7 8 0
1 21 5
3 14 1
3 4 2
3 2 2
4 51 5 1 3
2 1 3
輸出 #1複製221
說明/提示
資料規模:
對於 30%30% 的資料: 1 \leq n \leq 10,1 \leq m \leq 101≤n≤10,1≤m≤10;
對於 70%70% 的資料: 1 \leq n \leq ^3, 1 \leq m \leq ^31≤n≤10
3,1≤m≤103;
對於 100%100% 的資料: 1\le n \leq ^5, 1\le m \leq ^5,1\le r\le n,1\le p \le 2^-11≤n≤10
5,1≤m≤10
5,1≤r≤n,1≤p≤2
31−1。
當做模板用就行,不解釋了
#
include
#define
inf0x7fffffff
#define
lllong
long
#define
intlong
long
//#define double long double
#define
eps1e-8
//#define mod 1e9+7
using
namespace std;
//const int mod=1e9+7;
const
int m=
1e7+5;
const
int n=
1e6+5;
//?????????? 4e8
struct
node
e[n]
;struct
tree
t[n]
;int dep[n]
,dfn[n]
,son[n]
,sz[n]
,fa[n]
;int n,m,root,mod;
int tot=
1,head[n]
;int a[n]
,num,top[n]
,w[n]
;void
add(
int x,
int y)
void
addedge
(int x,
int y)
void
dfs1
(int x,
int pre)}}
void
dfs2
(int x,
int pre)
}void
bulid
(int q,
int l,
int r)
int mid=
(l+r)
>>1;
bulid
(q<<
1,l,mid)
;bulid
(q<<1|
1,mid+
1,r)
; t[q]
.val=
(t[q<<1]
.val+t[q<<1|
1].val)
%mod;
}void
spread
(int q)
}void
change
(int q,
int l,
int r,
int v)
spread
(q);
int mid=
(t[q]
.l+t[q]
.r)>>1;
if(l<=mid)
change
(q<<
1,l,r,v);if
(midchange
(q<<1|
1,l,r,v)
; t[q]
.val=
(t[q<<1]
.val+t[q<<1|
1].val)
%mod;
}int
ask(
int q,
int l,
int r)
void
mson
(int x,
int v)
//以x為根的子樹的所有節點+v
intqson
(int x)
//以x為根的子樹的所有節點+v 的和
void
mchain
(int x,
int y,
int z)
//修改鏈 (x->y)
if(dep[x]
>dep[y]
)swap
(x,y)
;change(1
,dfn[x]
,dfn[y]
,z);
}int
qchain
(int x,
int y)
//查詢鏈 (x->y)
if(dep[x]
>dep[y]
)swap
(x,y)
; ans=
(ans+
ask(
1,dfn[x]
,dfn[y]))
%mod;
return ans%mod;
}void
solve()
dfs1
(root,root)
;dfs2
(root,root)
;bulid(1
,1,n);
while
(m--
)else
if(f==2)
else
if(f==3)
else
printf
("%lld\n"
,qson
(x));}
}signed
main()
P3384 輕重鏈剖分(樹剖模板)
如題,已知一棵包含 nn 個結點的樹 連通且無環 每個節點上包含乙個數值,需要支援以下操作 操作 11 格式 1 x y z1xyz 表示將樹從 xx 到 yy 結點最短路徑上所有節點的值都加上 zz。操作 22 格式 2 x y2xy 表示求樹從 xx 到 yy 結點最短路徑上所有節點的值之和。操...
洛谷 P3384 模板 輕重鏈剖分(樹鏈剖分)
簡單點說,就是把一棵樹變成多條鏈。這裡說的是重鏈剖分。在遍歷一顆樹的時候,我們強制從父親節點走向兒子時,先走所有兒子中以兒子為根的子樹最大的那個兒子。其他的兒子不管什麼順序都可。這樣就可以把dfs序作為鏈。例如上面這棵樹,邊上的藍色數字就是遍歷順序。說一些定義 重邊 父親結點和重兒子連成的邊 輕邊 ...
樹鏈剖分 P3384 模板 樹鏈剖分
題目描述 戳這裡 題解 其實樹剖的重點就在於輕重鏈,這篇文章寫的很好 然而我線段樹寫得全是問題,改了半天2333 如下 include include include using namespace std const int maxn 100005 int n,m,root,tt,tot,lnk ...