[ZJOI2008]树的统计-树链剖分
Posted wangyifan124
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ZJOI2008]树的统计-树链剖分相关的知识,希望对你有一定的参考价值。
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6+5; #define mid ((l+r)>>1) #define left_son root<<1,l,mid #define right_son root<<1|1,mid+1,r int n,m; int e,begin[maxn],next[maxn],to[maxn],w[maxn],a[maxn]; struct segment_tree{ int sum,l,r,mark,maxw; }tree[maxn<<2]; int son[maxn],id[maxn],father[maxn],cnt,deep[maxn],size[maxn],top[maxn],_map[maxn]; inline void add(int x,int y){ to[++e] = y; next[e] = begin[x]; begin[x] = e; } inline void pushup(int root){ tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum; tree[root].maxw = max(tree[root<<1].maxw,tree[root<<1|1].maxw); } inline void build(int root,int l,int r){ tree[root].l = l; tree[root].r = r; tree[root].mark = 0; if(l == r){ tree[root].sum = w[_map[l]]; tree[root].maxw = w[_map[l]]; return; } build(left_son); build(right_son); pushup(root); } inline void update(int root,int l,int r,int num,int k){ if(l == r){ tree[root].sum = k; tree[root].maxw = k; return; } if(num <= mid)update(left_son,num,k); else update(right_son,num,k); pushup(root); } inline int query(int root,int l,int r,int al,int ar){ if(al > r || ar < l)return 0; if(al <= l && ar >= r)return tree[root].sum; return query(left_son,al,ar)+query(right_son,al,ar); } inline int query_max_node(int root,int l,int r,int al,int ar){ if(al > r || ar < l)return -999999999; if(al <= l && ar >= r)return tree[root].maxw; return max(query_max_node(left_son,al,ar),query_max_node(right_son,al,ar)); } inline int query_range(int x,int y){ int ans = 0; while(top[x] != top[y]){ if(deep[top[x]] < deep[top[y]])swap(x,y); ans += query(1,1,cnt,id[top[x]],id[x]); x = father[top[x]]; } if(deep[x] > deep[y])swap(x,y); ans += query(1,1,cnt,id[x],id[y]); return ans; } inline int query_max_range(int x,int y){ int ans = -999999999; while(top[x] != top[y]){ if(deep[top[x]] < deep[top[y]])swap(x,y); ans = max(ans,query_max_node(1,1,cnt,id[top[x]],id[x])); x = father[top[x]]; } if(deep[x] > deep[y])swap(x,y); ans = max(ans,query_max_node(1,1,cnt,id[x],id[y])); return ans; } inline void dfs1(int x,int fa,int dep){ deep[x] = dep; father[x] = fa; size[x] = 1; int maxson = -999999999; for(int i = begin[x];i;i = next[i]){ int y = to[i]; if(y == fa)continue; dfs1(y,x,dep+1); size[x] += size[y]; if(size[y] > maxson)son[x] = y,maxson = size[y]; } } inline void dfs2(int x,int ntop){ id[x] = ++cnt; top[x] = ntop; _map[id[x]] = x; if(!son[x])return; dfs2(son[x],ntop); for(int i = begin[x];i;i = next[i]){ int y = to[i]; if(y == father[x] || y == son[x])continue; dfs2(y,y); } } int main(){ cin>>n; for(int i = 1,u,v;i < n;i++){ scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(int i = 1;i <= n;i++)scanf("%d",&w[i]); dfs1(1,0,1); dfs2(1,1); build(1,1,n); cin>>m; while(m--){ string ask; int u,v; cin>>ask>>u>>v; if(ask == "CHANGE")update(1,1,cnt,id[u],v); if(ask == "QMAX")printf("%d ",query_max_range(u,v)); if(ask == "QSUM")printf("%d ",query_range(u,v)); } return 0; }
以上是关于[ZJOI2008]树的统计-树链剖分的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1036: [ZJOI2008]树的统计Count (树链剖分)
1036: [ZJOI2008]树的统计Count(树链剖分)