给出一棵n个节点的树,每个节点都有一种颜色c[i]。
q次询问[l,r]路径上的点的权值和vjwi。每一个节点的权值就是当前节点的颜色值v[c[i]]和从l到该节点经过该颜色的次数num[c[i]]对应的w值w[num[c[i]]之间的乘积(很绕,看题目描述吧,懒得描述了)
这是树上莫队。分块是对子树进行。如果一个某一个子树的size满足块大小,则分成一块。
void dfs1(int t, int f){
sz[t]=1;
fa[t] = f;
dp[t] = dp[f]+1;
dfn[t]=++clk;
st.push(t);
int cur_p = st.size();
for(int v : g[t]){
if(v==f)continue;
dfs1(v,t);
if(sz[v] > sz[hs[t]]) hs[t] = v;
sz[t]+=sz[v];
if(st.size() - cur_p >= block_size){
//get one block
while(st.size() > cur_p){
block_num[st.top()] = cur_block;
st.pop();
}
cur_block++;
}
}
if(t==1){
while(!st.empty()){
block_num[st.top()] = cur_block;
st.pop();
}
cur_block++;
}
}
最后就是正常的莫队操作了。
树上莫队的难点在于[l,r]的边界移动。
假设从[l,r]移动到[l',r'], 将l移动到l'或者r移动到r'时,对