链接:https://ac.nowcoder.com/acm/problem/207389
来源:牛客网
系统中有一棵n个点的完全k叉树,现给出它的BFS层序遍历序列a_ia
i
(即从根节点开始,每一层从左向右遍历),请你还原这棵树,并返回加密后的答案。
答案加密方法:所有边两个端点异或的和,即\sum\limits_{i=1}^{n-1}u_i\ xor\ v_i
i=1
∑
n−1
u
i
xor v
i
,其中(u_i, v_i)(u
i
,v
i
)为一条树上的边。
下面给出完全二叉树的定义:若设二叉树的深度为k,除第 k 层外,其它各层 (1~k-1) 的结点数都达到最大个数,第k层所有的结点都连续集中在最左边。
请你根据这个定义进行适度推广,得到完全k叉树的含义。
示例1
输入
复制
2,[1,2,3,4,5]
返回值
复制
18
说明
树边为(1, 2), (1, 3), (2, 4), (2, 5),加密过程为(12)+(13)+(24)+(25),答案为18。
样例1构成的完全二叉树为:
示例2
输入
复制
3,[1,2,3,4,5]
返回值
复制
17
说明
树边为(1, 2), (1, 3), (1, 4), (2, 5),加密过程为(12)+(13)+(14)+(25),答案为17。
样例2构成的完全三叉树为:
备注:
数据满足:1\leq n,k\leq 10^5, 1\leq a_i\leq 10^91≤n,k≤10
5
,1≤a
i
≤10
9
这题在上一个赛季出现过类似的,只不过节点更多了,开始范围和结束范围变了。道理是一样的,子节点异或上根节点的值相加。bfs模拟一遍就好了,只是要注意子节点的起始和结束范围。我们多画几个就知道,子节点的范围是
(root x k)+k-2<=i<=(root x k)+1;
也就是根节点乘于k加上k-2到根节点乘于k+1.
然后用队列模拟一遍即可,需要注意的是vector下标从0开始的,需要减一对应其值。
还有一个方法是既然要求的是所有的子节点异或上根节点的值,我们直接遍历所有的根节点即可
BFS,DFS都不是我擅长的。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param k int整型 表示完全k叉树的叉数k
* @param a int整型vector 表示这棵完全k叉树的Bfs遍历序列的结点编号
* @return long长整型
*/
#define ll long long
long long tree2(int k, vector<int>& a) {
// write code here
ll sum=0;
queue<ll>q;
q.push(1);
while(q.size())
{
ll t=q.front();
q.pop();
for(int i=t*k-k+2;i<=k*t+1&&i<=a.size();i++)
{
ll ans=a[i-1]^a[t-1];
sum+=ans;
q.push(i);
}
}
//for(int i=1;i<n;i++)
//{
//sum+=a[i]^a[(i-1)/k];//将所有根结点与它的叶子结点异或,并将结果相加,所以遍历叶子结点就ok,从1开始一直到最后一个,根节点为i-1/k,这样逆过来想就十分简单了
//}
return sum;
}
};