HDU6191(dfs序 + 可持久Trie树)

Query on A Tree

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 54    Accepted Submission(s): 17

Problem Description Monkey A lives on a tree, he always plays on this tree.

One day, monkey A learned about one of the bit-operations, xor. He was keen of this interesting operation and wanted to practise it at once.

Monkey A gave a value to each node on the tree. And he was curious about a problem.

The problem is how large the xor result of number x and one node value of label y can be, when giving you a non-negative integer x and a node label u indicates that node y is in the subtree whose root is u(y can be equal to u).

Can you help him?

 

Input There are no more than 6 test cases.

For each test case there are two positive integers n and q, indicate that the tree has n nodes and you need to answer q queries.

Then two lines follow.

The first line contains n non-negative integers 

V1,V2,,Vn, indicating the value of node i.

The second line contains n-1 non-negative integers 

F1,F2,Fn1

Fi means the father of node 

i+1.

And then q lines follow.

In the i-th line, there are two integers u and x, indicating that the node you pick should be in the subtree of u, and x has been described in the problem.


2n,q105


0Vi109


1Fin, the root of the tree is node 1.


1un,0x109

 

Output For each query, just print an integer in a line indicating the largest result.

 

Sample Input

2 2 1 2 1 1 3 2 1  

Sample Output

2 3  

Source
2017ACM/ICPC广西邀请赛-重现赛(感谢广西大学)  

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  6193 6192 6191 6190 6189 

解题思路:我们用dfs序把节点hash到一个数组,然后对这个数组建n棵前缀字典树就行,每次查询直接用历史版本搞就行。跟区间第k小一个道理

#define OPENSTACK
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 10;
int n, q;
int cnt, tot;
int Rank[maxn];//节点在数组上的位置
int L[maxn];//dfs进入时间戳
int R[maxn];//dfs出时间戳
int v[maxn];//顶点权值
int T[maxn];//n棵字典树的根节点
struct node{
    int sum;
    int l, r;
    node(){
        sum = 0;
        l = 0;
        r = 0;
    }
}Tree[maxn<<6];
int head[maxn];
int ee = 0;
struct edge{
    int v;
    int last;
}Edge[maxn];
void add(int u, int v)
{
    Edge[ee].v = v;
    Edge[ee].last = head[u];
    head[u] = ee++;
}
void dfs(int u)
{
    L[u] = ++cnt;
    for(int i = head[u]; i != -1 ; i = Edge[i].last)
    {
        int v = Edge[i].v;
        dfs(v);
    }
    R[u] = cnt;
}
void Insert(int root, int x, int value)
{
    int p = root;
    for(int i = 30; i >= 0; i--)
    {
        int num = (x>>i)&1;
        if(num == 0)
        {
            if(Tree[p].l == 0)
            {
                Tree[p].l = tot++;
                p = Tree[p].l;
                Tree[p].sum += value;
            }
            else
            {
                p = Tree[p].l;
                Tree[p].sum += value;
            }
        }
        else
        {
            if(Tree[p].r == 0)
            {
                Tree[p].r = tot++;
                p = Tree[p].r;
                Tree[p].sum += value;
            }
            else
            {
                p = Tree[p].r;
                Tree[p].sum += value;
            }
        }
    }
}
int update(int pa, int x)
{
    int now = tot++;
    int p = now;
    for(int i = 30; i >= 0; i--)
    {
        int num = (x>>i)&1;
        if(num == 0)
        {
            Tree[p].r = Tree[pa].r;
            Tree[p].l = tot++;
            p = Tree[p].l;
            pa = Tree[pa].l;
            Tree[p].sum = Tree[pa].sum + 1;
        }
        else
        {
            Tree[p].l = Tree[pa].l;
            Tree[p].r = tot++;
            p = Tree[p].r;
            pa = Tree[pa].r;
            Tree[p].sum = Tree[pa].sum + 1;
        }
    }
    return now;

}
int query(int p1, int p2, int x)
{
    int d;
    int ans = 0;
    for(int i = 30; i >= 0; i--)
    {
        int num = (x>>i)&1;
        if(num == 0)
        {
            if(Tree[p2].r == 0)
            {
                p2 = Tree[p2].l;
                p1 = Tree[p1].l;
                continue;
            }
            d = Tree[Tree[p2].r].sum - Tree[Tree[p1].r].sum;
            if(d > 0)
            {
                ans += (1<<i);
                p1 = Tree[p1].r;
                p2 = Tree[p2].r;
            }
            else
            {
                p1 = Tree[p1].l;
                p2 = Tree[p2].l;
            }
        }
        else
        {
            if(Tree[p2].l == 0)
            {
                p2 = Tree[p2].r;
                p1 = Tree[p1].r;
                continue;
            }
            d = Tree[Tree[p2].l].sum - Tree[Tree[p1].l].sum;
            if(d > 0)
            {
                ans += (1<<i);
                p1 = Tree[p1].l;
                p2 = Tree[p2].l;
            }
            else
            {
                p1 = Tree[p1].r;
                p2 = Tree[p2].r;
            }
        }
    }
    return ans;
}
void init()
{
    cnt = 0;
    tot = 0;
    dfs(1);
    for(int i = 1; i <= n; i++)
    {
        Rank[L[i]] = v[i];
    }
}
int main()
{


#ifdef OPENSTACK
        int size = 128<< 20; // 64MB
        char *p = (char*)malloc(size) + size;
        #if (defined _WIN64) or (defined __unix)
            __asm__("movq %0, %%rsp\n" :: "r"(p));
        #else
            __asm__("movl %0, %%esp\n" :: "r"(p));
        #endif
    #endif

//    #ifdef OPENSTACK
//        exit(0);
//    #else
//        return 0;
//    #endif
    OPENSTACK;
    //freopen("C:\\Users\\creator\\Desktop\\in.txt","r",stdin) ;
    //freopen("C:\\Users\\creator\\Desktop\\out.txt","w",stdout) ;
    while(~scanf("%d%d", &n, &q))
    {
        for(int i = 0; i < (maxn<<6) - 1; i++)
        {
            Tree[i].l = 0;
            Tree[i].r = 0;
            Tree[i].sum = 0;
        }
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &v[i]);
        }
        int f;
        ee = 0;
        memset(head, -1, sizeof(head));
        for(int i = 1; i < n; i++)
        {
            scanf("%d", &f);
            add(f, i + 1);
        }
        init();
        T[0] = ++tot;
        for(int i = 1; i <= n; i++)
        {
            Insert(T[0], Rank[i], 1);
        }
        for(int i = 1; i <= n; i++)
        {
            Insert(T[0], Rank[i], -1);
        }
        for(int i = 1; i <= n; i++)
        {
            T[i] = update(T[i - 1], Rank[i]);
        }
        int uu, xx;
        for(int i = 1; i <= q; i++)
        {
            scanf("%d%d", &uu, &xx);
            printf("%d\n", query(T[L[uu] - 1], T[R[uu]], xx));

        }
    }
    return 0;
}

    原文作者:Trie树
    原文地址: https://blog.csdn.net/creatorx/article/details/77752061
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞