Marge is already preparing for Christmas and bought a beautiful tree, decorated with shiny ornaments. Her Christmas tree can be represented as a complete binary tree composed of N nodes, numbered from 1to N and rooted on node 1. Each node has an integer value associated to it, representing its shininess.
The shininess of the h - th level of the tree is the sum of the shininess of all the nodes with depth h and the shininess of the tree is the largest value of shininess of its levels.
Nicoleta has a crush on a girl and wants to give her a part of Marge's beautiful tree. To do so, he will choose a node u and give his crush the subtree rooted at node u, including u. However, he doesn't want to get in (too much) trouble with Marge, so he will consider some candidates before making the cut.
Nicoleta has M candidate nodes to be the root of the cut subtree. For each candidate, Nicoleta wants to know what is the value of shininess of the remaining tree.
Input
The first line of the input contains a three integers N (2 ≤ N ≤ 105) and M (1 ≤ M ≤ 105) and w (0 ≤ w ≤ 104), indicating, respectively, the number of nodes of the tree, the number of candidate nodes and the shininess of node 1.
Each of the next N - 1 lines contains three integers u (2 ≤ u ≤ N) , v (1 ≤ v ≤ N) and w (0 ≤ w ≤ 104), indicating that node u is a child of node v and has shininess w.
M lines follow, each with a single integer u (2 ≤ u ≤ N), indicating the number of a candidate node.
Output
For each candidate node, in the order that they appear in the input, output a single line containing a single integer: the shininess of the remaining tree.
Example
6 2 3
4 1 1
5 1 4
2 4 7
3 4 6
6 5 5
4
5
5
13
Note
More about complete binary trees: https://en.wikipedia.org/wiki/Binary_tree#Types_of_binary_trees
题解:题目给出一个完全二叉树,并定义一个此树中每层的权值为该层的每个点的权值之和,总的权为每层中最大的那个.
让我们求去掉以u为根的子树后,所得的剩下的树的权(shinness). 由于是完全二叉树,则每个点的儿子的下标为id*2,id*2+1,并且每一层的下标范围为[2^i,2^(i+1)-1](第i层,从0开始计数).那么去掉一颗子树后,损失的信息就可以区间求和来快速算出来, 总共的该层的权重之和也可以快速算出来.
用线段树,树状数组,ST表什么的都可以哇~~.
首先建立完全二叉树根据预处理得到的每个点的siz[i]数组大小(以i为根的子树元素有多少个).建立正确的完全二叉树,然后为其建立新的下标,对应下标赋予正确的权值.然后对于每一个询问u,我们首先找根节点1,看去掉u这一层能否影响到1这一层,然后向下递归就好啦.
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=100010; int val[maxn],dfn[maxn]; int siz[maxn],data[maxn]; int sum[maxn<<2]; vector<int>G[maxn]; void dfs(int u) { siz[u]=1; for(int i=0;i<G[u].size();i++){ dfs(G[u][i]); siz[u]+=siz[G[u][i]]; } } void DFS(int u,int index) { dfn[u]=index; if(G[u].size()==0)return ; else if(G[u].size()==1){ DFS(G[u][0],index*2); } else{ if(siz[G[u][0]]>=siz[G[u][1]]){ DFS(G[u][0],index*2); DFS(G[u][1],index*2+1); } else{ DFS(G[u][0],index*2+1); DFS(G[u][1],index*2); } } } void build(int l,int r,int rt) { if(l==r){ sum[rt]=data[l]; return ; } int mid=(l+r)/2; build(l,mid,rt*2); build(mid+1,r,rt*2+1); sum[rt]=sum[rt*2]+sum[rt*2+1]; } int querysum(int L,int R,int l,int r,int rt) { if(L<=l&&R>=r)return sum[rt]; int ans=0; int mid=(l+r)/2; if(L<=mid)ans+=querysum(L,R,l,mid,rt*2); if(R>=mid+1)ans+=querysum(L,R,mid+1,r,rt*2+1); return ans; } int main() { int n,m,w; cin >> n >> m >> w; val[1]=w; for(int i = 1; i <= n-1; i++){ int u, v, w; cin >> u >> v >> w; G[v].push_back(u); val[u]=w; } dfs(1); DFS(1,1); for(int i = 1; i <= n; i++){ data[dfn[i]]=val[i]; } build(1,n,1); while(m--){ int u,ans=0; cin >> u; u=dfn[u]; int now1=1,siz1=1; int now2=u,siz2=1; while(now1<=n){ if(now2>=now1&&now2<=min(n,now1+siz1-1)){ ans=max(ans,querysum(now1,min(n,now1+siz1-1),1,n,1)-querysum(now2,min(n,now2+siz2-1),1,n,1)); now2*=2; siz2*=2; } else{ ans=max(ans,querysum(now1,min(n,now1+siz1-1),1,n,1)); } now1*=2; siz1*=2; } cout<<ans<<endl; } return 0; }