HDU 6191 Query on A Tree

可持久字典树。

询问子树可以转化为询问一段区间,因此可以对树的$dfs$序进行操作。因为是在一群数字中找一个数字和已知数字异或最大,所以可以想到字典树。保存前缀字典树,然后询问区间$[L,R]$的时候,只要$R$的字典树减去$L-1$的字典树就是区间$[L,R]$上的的数字构成的字典树。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 100000 + 10;
int n, a[maxn];
int sz, h[maxn], to[maxn], nx[maxn];
int L[maxn], R[maxn];
int num, b[2 * maxn];
int q;
struct Node {
  int son[2];
  int cnt;
}s[65 * maxn];
int root[2 * maxn];

void addedge(int u, int v) {
  to[sz] = v;
  nx[sz] = h[u];
  h[u] = sz;
  sz ++;
}

void dfs(int x) {
  b[++ num] = a[x];
  L[x] = num;
  for(int i = h[x]; i != -1; i = nx[i]) {
    dfs(to[i]);
  }
  b[++ num] = a[x];
  R[x] = num;
}

int addnode() {
  num ++;
  s[num].son[0] = -1;
  s[num].son[1] = -1;
  s[num].cnt = 0;
  return num;
}

int work(int x, int y) {
  int res = 0;
  int p1 = root[L[x] - 1];
  int p2 = root[R[x]];
  for(int i = 30; i >= 0; i --) {
    int u = (1 << i) & y;
    u = u ? 1 : 0;
    if(p1 == -1) {
      if(s[p2].son[u ^ 1] != -1) {
        res = res + (1 << i);
        p2 = s[p2].son[u ^ 1];
      } else {
        p2 = s[p2].son[u];
      }
    } else {
      if(s[p2].son[u ^ 1] == -1) {
        p1 = s[p1].son[u];
        p2 = s[p2].son[u];
      } else {
        if(s[p1].son[u ^ 1] == -1) {
          res = res + (1 << i);
          p1 = s[p1].son[u ^ 1];
          p2 = s[p2].son[u ^ 1];
        } else {
          if(s[s[p1].son[u ^ 1]].cnt < s[s[p2].son[u ^ 1]].cnt) {
            res = res + (1 << i);
            p1 = s[p1].son[u ^ 1];
            p2 = s[p2].son[u ^ 1];
          } else {
            p1 = s[p1].son[u];
            p2 = s[p2].son[u];
          }
        }
      }
    }
  }
  return res;
}

int main() {

  while(~scanf("%d%d", &n, &q)) {
    num = sz = 0;
    for(int i = 1; i <= n; i ++) {
      h[i] = -1;
    }
    for(int i = 1; i <= n; i ++) {
      scanf("%d", &a[i]);
    }
    for(int i = 1; i <= n - 1; i ++) {
      int x;
      scanf("%d", &x);
      addedge(x, i + 1);
    }
    dfs(1);

    num = 0;
    root[0] = 0;
    s[0].son[0] = -1;
    s[0].son[1] = -1;
    s[0].cnt = 0;

    for(int i = 1; i <= 2 * n; i ++) {
      root[i] = addnode();
      int p1 = root[i - 1];
      int p2 = root[i];
      s[p2].son[0] = s[p1].son[0];
      s[p2].son[1] = s[p1].son[1];
      s[p2].cnt = s[p1].cnt;
      for(int j = 30; j >= 0; j --) {
        int x = (1 << j) & b[i];
        x = x ? 1 : 0;
        if(p1 == -1) {
          int id = addnode();
          s[id].cnt ++;
          s[p2].son[x] = id;
          p2 = id;
        } else {
          p1 = s[p1].son[x];
          int id = addnode();
          if(p1 != -1) {
            s[id].son[0] = s[p1].son[0];
            s[id].son[1] = s[p1].son[1];
          }
          if(p1 != -1) {
            s[id].cnt = s[p1].cnt + 1;
          } else {
            s[id].cnt = 1;
          }
          s[p2].son[x] = id;
          p2 = id;
        }
      }
    }

    for(int i = 1; i <= q; i ++) {
      int x, y;
      scanf("%d%d", &x, &y);
      int ans = work(x, y);
      printf("%d\n", ans);
    }
  }
  return 0;
}

  

posted @ 2017-09-08 08:46  Fighting_Heart  阅读(264)  评论(0编辑  收藏  举报