題目描述有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個操作,分為三種:
操作 1 :把某個節點 x 的點權增加 a 。
操作 2 :把某個節點 x 為根的子樹中所有點的點權都增加 a 。
操作 3 :詢問某個節點 x 到根的路徑中所有點的點權和。
輸入格式
第一行包含兩個整數 n, m 。表示點數和運算元。
接下來一行 n 個整數,表示樹中節點的初始權值。
接下來 n-1 行每行兩個正整數 from, to , 表示該樹中存在一條邊 (from, to) 。
再接下來 m 行,每行分別表示一次操作。其中第乙個數表示該操作的種類( 1-3 ) ,之後接這個操作的引數( x 或者 x a ) 。
輸出格式
對於每個詢問操作,輸出該詢問的答案。答案之間用換行隔開。
輸入輸出樣例輸入 #1
5 51 2 3 4 5
1 21 4
2 32 5
3 31 2 1
3 52 1 2
3 3
輸出 #16913
說明/提示對於 100% 的資料, n,m<=100000 ,且所有輸入資料的絕對值都不會超過 106
10^6
106 。
解釋:樹鏈剖分題,查詢以x為根的子樹,其實就是查詢[dfn[x]
,dfn
[x]+
sz[x
]−1]
.[dfn[x],dfn[x]+sz[x]-1].
[dfn[x
],df
n[x]
+sz[
x]−1
].,其中dfn
[x
]dfn[x]
dfn[x]
為d fs
dfsdf
s序,sz[
x]
sz[x]
sz[x
]表示以x為根的節點個數。其他都是裸模板
#include #include #include #include #define ll long long
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
inline char nc()
template inline void read(register tp &s)
const ll n=200000,m=200000;
ll n,idx,dfn[n],seq[n],u[n],v[n],w[n],val[n],fa[n],dep[n],top[n],sz[n],hvy[n];
ll lazy[n]=;
ll tot,lnk[n],ter[m],nxt[m],seg[n<<2];
void add(ll u,ll v)
void dfs1(ll u,ll f)
void modify(ll l,ll r,ll rt,ll l,ll r,ll val)
ll mid=(l+r)>>1;
if(l<=mid) modify(l,r,lson,l,mid,val);
if(r>mid) modify(l,r,rson,mid+1,r,val);
pushup(rt);
}ll query(ll x,ll y,ll rt,ll l,ll r)ll m=0;
int main()
dfs1(1,0),dfs2(1,1);
build(1,1,n);
while(m--)else if(cmd==2)else
}return 0;
}
洛谷P3178 HAOI2015 樹上操作
有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個操作,分為三種 操作 1 把某個節點 x 的點權增加 a 操作 2 把某個節點 x 為根的子樹中所有點的點權都增加 a 操作 3 詢問某個節點 x 到根的路徑中所有點的點權和。輸入格式 第一行包含兩個整數 n,m 表示點數和運算元。...
洛谷 P3178 HAOI2015 樹上操作
這篇題解原發於我的blog 這是一道樹鏈剖分的板子題,純粹的模板題事實上模板題比他難 事實上只要做過這道題p3384 模板 樹鏈剖分就可以我把題目難度提公升了 畢竟我是剛切完板子題的人,初生牛犢不怕虎,直接再打一遍練練手被逼的 記住因為這題沒有提供取模的數,因為 10 6 times10 5 2 1...
洛谷P3178 HAOI 2015 樹上操作
題目 樹剖裸題,這個題更可以深刻的理解樹剖中把樹上的節點轉換為區間的思想。要注意在區間上連續的節點,一定是在一棵子樹中。include define int long long define ls left,mid,root 1 define rs mid 1,right,root 1 1 defi...