📌  相关文章
📜  使用BIT查询彩色树的子树中不同颜色的数量

📅  最后修改于: 2021-04-17 13:42:54             🧑  作者: Mango

先决条件: BIT,DFS

给定带有“ n”个节点的根树T,每个节点都有一种颜色,该颜色由数组color []表示(color [i]以整数形式表示第i个节点的颜色)。响应以下类型的“ Q”查询:

  • 独特的u –打印以“ u”为根的子树下的不同颜色的节点数

例子:

1
           / \
          2   3
         /|\  | \
        4 5 6 7  8
             /| \
            9 10 11
color[] = {0, 2, 3, 3, 4, 1, 3, 4, 3, 2, 1, 1} 
Indexes    NA 1  2  3  4  5  6  7  8  9 10  11
(Node Values and colors start from index 1)

distinct 3 -> output should be '4'.
There are six different nodes in the subtree rooted with
3, nodes are 3, 7, 8, 9, 10 and 11. These nodes have
four distinct colors (3, 4, 2 and 1)

distinct 2 -> output should be '3'.
distinct 7 -> output should be '3'.       

分步构建解决方案:

  1. 使用DFS展平树;将每个节点的访问时间和结束时间存储在两个数组中, vis_time [i]存储第i个节点的访问时间,而end_time [i]存储结束时间。
  2. 在同一DFS调用中,将每个节点的颜色值存储在flat_tree []数组中,索引为第i个节点的vis_time [i]end_time [i]
    注意:数组flat_tree []的大小为2n。

现在,问题已减少到为指定类型的每个查询在数组flat_tree []中查找[vis_time [u],end_time [u]]范围内的不同元素数。为此,我们将离线处理查询(以与问题中提供的顺序不同的顺序处理查询并存储结果,最后以问题中指定的顺序为每个结果打印结果)。

脚步:

  1. 首先,我们预处理数组flat_tree [] ;我们维护一个table [] (向量数组), table [i]将向量包含在flat_tree []中所有值为i的索引中。也就是说,如果flat_tree [j] = i ,则table [i]将具有其元素j之一
  2. 在BIT中,如果希望flat_tree []的第i个元素在query()方法中计数,则在第i个索引处更新“ 1”。现在,我们维护另一个数组traverser [] ; traverser [i]包含指向table [i]的下一个元素的指针,该指针尚未在BIT中标记。
  3. 现在,我们更新BIT并在flat_tree []中的每个元素首次出现时将其设置为“ 1”,并将对应的traverser []递增“ 1”(如果flat_tree [i]首次出现,则traverser [flat_tree [i]]以“ 1”递增)以指向该元素的下一个匹配项。
  4. 现在,我们的BIT查询(R)函数将返回flat_tree [][1,R]范围内的不同元素数。
  5. 我们以vis_time []递增的顺序对所有查询进行排序,让l i表示vis_time [i]r i表示end_time [i] 。以l i的升序对查询进行排序为我们提供了优势,因为在处理第i个查询时,我们以后不会再看到’ l ‘小于l i的任何查询。因此,我们可以从BIT中删除直到l i – 1的所有元素出现,并使用traverser []数组添加它们的下一个出现。然后query(R)将返回[l i ,r i ]范围内的不同元素数。
// A C++ program implementing the above design
#include
#define max_color 1000005
#define maxn 100005
using namespace std;
  
// Note: All elements of global arrays are
// initially zero
// All the arrays have been described above
int bit[maxn], vis_time[maxn], end_time[maxn];
int flat_tree[2 * maxn];
vector tree[maxn];
vector table[max_color];
int traverser[max_color];
  
bool vis[maxn];
int tim = 0;
  
//li, ri and index are stored in queries vector
//in that order, as the sort function will use
//the value li for comparison
vector< pair< pair, int> > queries;
  
//ans[i] stores answer to ith query
int ans[maxn];
  
//update function to add val to idx in BIT
void update(int idx, int val)
{
    while ( idx < maxn )
    {
        bit[idx] += val;
        idx += idx & -idx;
    }
}
  
//query function to find sum(1, idx) in BIT
int query(int idx)
{
    int res = 0;
    while ( idx > 0 )
    {
        res += bit[idx];
        idx -= idx & -idx;
    }
    return res;
}
  
void dfs(int v, int color[])
{
    //mark the node visited
    vis[v] = 1;
  
    //set visiting time of the node v
    vis_time[v] = ++tim;
  
    //use the color of node v to fill flat_tree[]
    flat_tree[tim] = color[v];
  
    vector::iterator it;
    for (it=tree[v].begin(); it!=tree[v].end(); it++)
        if (!vis[*it])
            dfs(*it, color);
  
  
    // set ending time for node v
    end_time[v] = ++tim;
  
    // setting its color in flat_tree[] again
    flat_tree[tim] = color[v];
}
  
//function to add an edge(u, v) to the tree
void addEdge(int u, int v)
{
    tree[u].push_back(v);
    tree[v].push_back(u);
}
  
//function to build the table[] and also add
//first occurrences of elements to the BIT
void hashMarkFirstOccurrences(int n)
{
    for (int i = 1 ; i <= 2 * n ; i++)
    {
        table[flat_tree[i]].push_back(i);
  
        //if it is the first occurrence of the element
        //then add it to the BIT and increment traverser
        if (table[flat_tree[i]].size() == 1)
        {
            //add the occurrence to bit
            update(i, 1);
  
            //make traverser point to next occurrence
            traverser[flat_tree[i]]++;
        }
    }
}
  
//function to process all the queries and store their answers
void processQueries()
{
    int j = 1;
    for (int i=0; i

输出:

Distinct colors in the corresponding subtree is:4
Distinct colors in the corresponding subtree is:3
Distinct colors in the corresponding subtree is:3
Time Complexity: O( Q * log(n) )