📜  在根目录树上执行给定的查询

📅  最后修改于: 2021-05-04 07:34:56             🧑  作者: Mango

给定一棵有根的树,不一定是二叉树。该树包含N个节点,标记为1到N。将以大小为N的数组A [1..N]的形式为您提供树。A [i]表示标记为i的节点的父节点的标签。为了清楚起见,您可以假定树满足以下条件。

任务是根据给定的查询类型执行以下操作。

  1. ADD,X,Y :将Y添加到节点X的值。
  2. ADDUP,X,Y :将Y添加到节点X的值。然后,将Y添加到A [X]的值(即X的父级)。然后,将Y添加到A [A [X]]的值(即A [X]的父级)。依此类推,直到将Y添加到根的值。

完成所有给定的操作后,将要求您回答以下几种类型的查询

  1. VAL,X :在节点X上打印值。
  2. VALTREE,X :打印以X为根(包括X)的子树中所有节点的值之和。

资料来源: Directi专访|套装13

例子:

说明:此问题是dfs的细微变化。在这种情况下,我们将节点的原始值和累加值存储在该对的向量中。我们做了2次dfs。

  1. dfs1用于离线查询,即计算每个节点的总和。
  2. dfs2子树总和存储在数组中。

现在,所有查询都可以在固定时间内得到答复。

dfs1之前的图
dfs1之前的图

dfs1之后的图
dfs1之后的图

以下是所需的实现:

C++
// C++ implementation to perform 
// above operations and queries
#include 
using namespace std;
  
/*
Code Parameters 
p->for every node first value is it's original value
and second value is it's addup value
subtree_sum[]-> to store the subtree_sum at every node
visit-> for dfs1
visit2->for dfs2
*/
vector > p;
vector adj[10000];
int subtree_sum[10000], visit[10000], visit2[10000];
  
int dfs1(int root)
{
    // for leaf node
    if (adj[root].size() == 0) {
  
        // if leaf node then add the addup
        // sum to it's original value
        p[root].first += p[root].second;
        return 0;
    }
  
    int sum = 0;
  
    for (int i = 0; i < adj[root].size(); i++) {
        if (visit[adj[root][i]] == 0) {
            dfs1(adj[root][i]);
  
            // add the addup sum of all the adjacent
            // neighbors to the current node
            p[root].second += p[adj[root][i]].second;
            visit[adj[root][i]] = 1;
        }
    }
  
    // process the root node
    p[root].first += p[root].second;
  
    return 0;
}
  
int dfs2(int root)
{
    if (adj[root].size() == 0) {
  
        // for the leaf node subtree_sum
        // will be it's own value
        subtree_sum[root] = p[root].first;
        return p[root].first;
    }
  
    int sum = p[root].first;
  
    for (int i = 0; i < adj[root].size(); i++) {
        if (visit2[adj[root][i]] == 0) {
            sum += dfs2(adj[root][i]);
            visit2[adj[root][i]] = 1;
        }
    }
  
    // calculate the subtree_sum
    // for the particular root node
    subtree_sum[root] = sum;
  
    return sum;
}
  
// Driver code
int main()
{
  
    int nodes = 7, m = 4, qu = 5, b;
    int a[] = { 0, 1, 2, 2, 2, 1, 2 };
    // for root node
    p.push_back(make_pair(0, 0));
  
    for (int i = 0; i < nodes; i++) {
  
        if (a[i] != 0)
            adj[a[i]].push_back(i + 1);
  
        // for every node
        p.push_back(make_pair(0, 0));
    }
  
    vector > > v;
    v.push_back(make_pair("ADD", make_pair(6, 76)));
    v.push_back(make_pair("ADDUP", make_pair(1, 49)));
    v.push_back(make_pair("ADD", make_pair(4, 48)));
    v.push_back(make_pair("ADDUP", make_pair(2, 59)));
  
    for (int i = 0; i < m; i++) {
        string s = v[i].first;
        int a = v[i].second.first;
        int b = v[i].second.second;
        if (s == "ADD")
            // adding to it's own value
            p[a].first += b;
  
        else
            // adding to it's addup value
            p[a].second += b;
    }
  
    // to process the offline  queries
    dfs1(1);
  
    // to store the subtree sum for every root node
    dfs2(1);
  
    vector > q;
    q.push_back(make_pair("VALTREE", 1));
    q.push_back(make_pair("VALTREE", 5));
    q.push_back(make_pair("VAL", 5));
    q.push_back(make_pair("VALTREE", 2));
    q.push_back(make_pair("VAL", 2));
    for (int i = 0; i < qu; i++) {
        string s = q[i].first;
        int a = q[i].second;
  
        if (s == "VAL")
            cout << p[a].first << "\n";
        else
            cout << subtree_sum[a] << "\n";
    }
}


Python3
# Python3 implementation to perform
# above operations and queries
p = []
adj = [0] * 10000
for i in range(10000):
    adj[i] = []
subtree_sum, visit, visit2 = [0] * 10000, [0] * 10000, [0] * 10000
  
# Code Parameters
# p->for every node first value is it's original value
# and second value is it's addup value
# subtree_sum[]-> to store the subtree_sum at every node
# visit-> for dfs1
# visit2->for dfs2
def dfs1(root: int) -> int:
  
    # for leaf node
    if len(adj[root]) == 0:
  
        # if leaf node then add the addup
        # sum to it's original value
        p[root][0] += p[root][1]
        return 0
  
    summ = 0
    for i in range(len(adj[root])):
        if visit[adj[root][i]] == 0:
            dfs1(adj[root][i])
  
            # add the addup sum of all the adjacent
            # neighbors to the current node
            p[root][1] += p[adj[root][i]][1]
            visit[adj[root][i]] = 1
  
    # process the root node
    p[root][0] += p[root][1]
  
    return 0
  
def dfs2(root: int) -> int:
    if len(adj[root]) == 0:
  
        # for the leaf node subtree_sum
        # will be it's own value
        subtree_sum[root] = p[root][0]
        return p[root][0]
  
    summ = p[root][0]
  
    for i in range(len(adj[root])):
        if visit2[adj[root][i]] == 0:
            summ += dfs2(adj[root][i])
            visit2[adj[root][i]] = 1
  
    # calculate the subtree_sum
    # for the particular root node
    subtree_sum[root] = summ
    return summ
  
# Driver Code
if __name__ == "__main__":
  
    nodes, m, qu = 7, 4, 5
    a = [0, 1, 2, 2, 2, 1, 2]
  
    # for root node
    p.append([0, 0])
  
    for i in range(nodes):
        if a[i] != 0:
            adj[a[i]].append(i + 1)
  
        # for every node
        p.append([0, 0])
  
    v = []
    v.append(("ADD", [6, 76]))
    v.append(("ADDUP", [1, 49]))
    v.append(("ADD", [4, 48]))
    v.append(("ADDUP", [2, 59]))
  
    for i in range(m):
        s = v[i][0]
        a = v[i][1][0]
        b = v[i][1][1]
  
        if s == "ADD":
  
            # adding to it's own value
            p[a][0] += b
        else:
  
            # adding to it's addup value
            p[a][1] += b
  
    # to process the offline queries
    dfs1(1)
  
    # to store the subtree sum for every root node
    dfs2(1)
  
    q = []
    q.append(["VALTREE", 1])
    q.append(["VALTREE", 5])
    q.append(["VAL", 5])
    q.append(["VALTREE", 2])
    q.append(["VAL", 2])
    for i in range(qu):
        s = q[i][0]
        a = q[i][1]
  
        if s == "VAL":
            print(p[a][0])
        else:
            print(subtree_sum[a])
  
# This code is contributed by
# sanjeev2552


输出:
291
0
0
107
59