洛谷 P3384 【模板】树链剖分(指针版)
2017-08-19 16:17
507 查看
题目>>https://www.luogu.org/problem/show?pid=3384
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int MAXN = 1e6 + 5; ll n,a,b,c,firs[MAXN],nex[MAXN],cnt = 0,q,r,m,num2[MAXN]; char s[233]; struct dd { ll f,t; }rad[MAXN]; void build(ll f,ll t) { rad[++cnt] = (dd){f,t}; nex[cnt] = firs[f]; firs[f] = cnt; } struct zt { ll sum,jia,sz; zt *lift,*right; }tree[MAXN]; ll num = 0; void build_tree(zt *root,ll l,ll r) { root->sum = root->jia = 0;root->sz = r - l + 1; if(l == r) return; root->lift = &tree[++num]; root->right = &tree[++num]; ll mid = l + r >> 1; build_tree(root->lift,l,mid); build_tree(root->right,mid + 1,r); } ll fa[MAXN],sz[MAXN],son[MAXN],deep[MAXN]; void dfs1(ll x,ll f) { fa[x] = f;sz[x] = 1;deep[x] = deep[f] + 1; for(int i = firs[x];i != -1;i = nex[i]) { ll v = rad[i].t; if(v != f) { dfs1(v,x); sz[x] += sz[v]; if(!son[x]||sz[son[x]] < sz[v]) son[x] = v; } } } ll top[MAXN],intu[MAXN],ji = 0,ed[MAXN]; void dfs2(ll x,ll topx) { top[x] = topx; intu[x] = ++ji; ed[x] = x; if(!son[x]) return; dfs2(son[x],topx); ed[x] = ed[son[x]]; for(int i = firs[x];i != -1;i = nex[i]) { ll v = rad[i].t; if(v != fa[x]&&v != son[x]) dfs2(v,v),ed[x] = ed[v]; } } void hs(zt *root) { root->sum = root->lift->sum + root->right->sum; } void xf(zt *root) { root->lift->jia += root->jia; root->right->jia += root->jia; root->lift->sum += root->lift->sz * root->jia; root->right->sum += root->right->sz * root->jia; root->jia = 0; } void change(zt *root,ll l,ll r,ll ql,ll qr,ll x) { if(l >= ql&&qr >= r) { root->jia += x; root->sum += root->sz * x; return; } if(root->jia) xf(root); ll mid = l + r >> 1; if(ql <= mid) change(root->lift,l,mid,ql,qr,x); if(qr > mid) change(root->right,mid + 1,r,ql,qr,x); hs(root); } void swap(ll &a,ll &b) { a^=b^=a^=b; } ll ask_sum(zt *root,ll l,ll r,ll ql,ll qr) { if(l >= ql&&qr >= r) return root->sum; if(root->jia) xf(root); ll mid = l + r >> 1,ans = 0; if(ql <= mid) ans = ask_sum(root->lift,l,mid,ql,qr); if(qr > mid) ans += ask_sum(root->right,mid + 1,r,ql,qr); return ans; } ll find_sum(ll a,ll b) { ll at = top[a],bt = top[b],ans = 0; while(at != bt) { if(deep[at] < deep[bt]) swap(at,bt),swap(a,b); ans += ask_sum(tree,1,n,intu[at],intu[a]); a = fa[at],at = top[a]; } if(deep[a] > deep[b]) swap(a,b); ans += ask_sum(tree,1,n,intu[a],intu[b]); return ans; } void find_change(ll a,ll b,ll x) { ll at = top[a],bt = top[b]; while(at != bt) { if(deep[at] < deep[bt]) swap(at,bt),swap(a,b); change(tree,1,n,intu[at],intu[a],x); a = fa[at],at = top[a]; } if(deep[a] > deep[b]) swap(a,b); change(tree,1,n,intu[a],intu[b],x); } int main() { scanf("%lld%lld%lld%lld",&n,&q,&r,&m); build_tree(tree,1,n); for(int i = 1;i <= n;i ++) firs[i] = -1; for(int i = 1;i <= n;i ++) scanf("%lld",&num2[i]); for(int i = 1;i < n;i ++) { scanf("%lld%lld",&a,&b); build(a,b); build(b,a); } dfs1(r,0); dfs2(r,r); for(int i = 1;i <= n;i ++) change(tree,1,n,intu[i],intu[i],num2[i]); for(int i = 1;i <= q;i ++) { scanf("%lld",&a); if(a == 1) scanf("%lld%lld%lld",&a,&b,&c),find_change(a,b,c); else if(a == 2) scanf("%lld%lld",&b,&c),cout<<find_sum(b,c) % m<<'\n'; else if(a == 3) scanf("%lld%lld",&b,&c),change(tree,1,n,intu[b],intu[ed[b]],c); else scanf("%lld",&b),cout<<ask_sum(tree,1,n,intu[b],intu[ed[b]]) % m<<'\n'; } }
相关文章推荐
- AC日记——【模板】树链剖分 洛谷 P3384
- 洛谷 P3384 【模板】树链剖分
- 洛谷P3384【模板】树链剖分 (树链剖分)
- 洛谷 P3384 【模板】树链剖分
- 洛谷P3384 【模板】树链剖分
- 洛谷——P3384 【模板】树链剖分
- 树链剖分 模板 洛谷P3384
- 洛谷 P3384 【模板】树链剖分
- 【洛谷P3384】【模板】树链剖分
- 洛谷P3384 【模板】树链剖分
- 洛谷P3384【模板】树链剖分
- 树剖模板(洛谷P3384 【模板】树链剖分)(树链剖分,树状数组,树的dfn序)
- 洛谷 P3384 【模板】树链剖分
- 洛谷P3384 【模板】树链剖分
- 洛谷树剖模板题 P3384 | 树链剖分
- P3384 【模板】树链剖分
- 洛谷.3384.[模板]树链剖分
- P3384 【模板】树链剖分
- P3384 【模板】树链剖分
- P3384 【模板】树链剖分