一棵树,其中的点分类,点有权值,在一条链上找到一类点中的最大值或总和;
树链剖分把树变成链;
把每个宗教单开一个线段树,维护区间总和和最大值;
宗教很多,需要动态开点;
树链剖分:
void dfs1(int x,int fa) { siz[x]=1; father[x]=fa; dep[x]=dep[fa]+1; for(int p=last[x];p;p=pre[p]) { int v=other[p]; if(v==fa) continue; dfs1(v,x); siz[x]+=siz[v]; if(siz[v]>siz[son[x]]) son[x]=v; } } void dfs2(int x,int tp) { id[x]=++cnt; top[x]=tp; if(!son[x]) return ; dfs2(son[x],tp); for(int p=last[x];p;p=pre[p]) { int v=other[p]; if(v==father[x]||v==son[x]) continue; dfs2(v,v); } } dfs1(1,0); dfs2(1,1);