您的位置:首页 > 产品设计 > UI/UE

HDU 6191 Query on A Tree 可持久化trie + dfs建树 || 启发式合并trie

2017-09-02 13:28 471 查看

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=6191

题意:

给出一棵树,树上每个点有点权,每次询问给出u x,求以u为根的子树中点权和x异或得到的最大值

思路:

dfs序建可持久化trie,然后就和普通可持久化trie一样了。还有启发式合并做法,一会学一下

#include <bits/stdc++.h>

using namespace std;

const int N = 100000 + 10;

int root
, son[N*35][2], sum[N*35];
int tot;
int len = 31;
bool bs[35];
int cnt, head
;
int num, in
, out
;
int a
;
struct edge
{
int to, next;
}g[N*2];
void init()
{
cnt = 0;
memset(head, -1, sizeof head);
tot = 0;
num = 0;
}
void add_edge(int v, int u)
{
g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;
}
void trie_insert(int p, int pre, int &x)
{
x = ++tot;
son[x][0] = son[pre][0], son[x][1] = son[pre][1];
//memcpy(son[x], son[pre], sizeof(int) * 2);
sum[x] = sum[pre] + 1;
if(! p) return;
trie_insert(p-1, son[pre][bs[p-1]], son[x][bs[p-1]]);
}
int trie_query(int p, int st, int en)
{
if(! p) return 0;
if(sum[son[en][bs[p-1]]] > sum[son[st][bs[p-1]]]) return trie_query(p-1, son[st][bs[p-1]], son[en][bs[p-1]]) + (1<<(p-1));
return trie_query(p-1, son[st][1-bs[p-1]], son[en][1-bs[p-1]]);
}
void dfs(int v, int fa)
{
in[v] = ++num;
for(int i = len-1; i >= 0; i--) bs[i] = 1 & (a[v] >> i);
trie_insert(len, root[in[v]-1], root[in[v]]);
for(int i = head[v]; i != -1; i = g[i].next)
{
int u = g[i].to;
if(u == fa) continue;
dfs(u, v);
}
out[v] = num;
}
int main()
{
int n, m;
while(~ scanf("%d%d", &n, &m))
{
init();
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
int x, u;
for(int i = 1; i <= n-1; i++)
{
scanf("%d", &x);
add_edge(x, i+1);
}
dfs(1, 0);
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &u, &x);
for(int j = len-1; j >= 0; j--) bs[j] = ! (1 & (x >> j));
int ans = trie_query(len, root[in[u]-1], root[out[u]]);
printf("%d\n", ans);
}
}
}


//2017.9.2 17:08

对于一个点,访问过它的子树后,就把子树的字典树合并到当前点的字典树上去,然后就可以查询以当前点为子树的查询了,是一种离线算法

#include <bits/stdc++.h>

using namespace std;

const int N = 100000 + 10;

int len = 31;
int cnt, head
;
int a
, ans
;

struct node
{
node *next[2];
node()
{
memset(next, 0, sizeof next);
}
};
node *root
;
struct qnode
{
int x, id;
qnode(int _x=0, int _id=0):x(_x), id(_id){}
};
vector<qnode> vec
;
struct edge
{
int to, next;
}g[N*2];
void init()
{
cnt = 0;
memset(head, -1, sizeof head);
}
void add_edge(int v, int u)
{
g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;
}
void trie_insert(node *root, int val)
{
node *p = root;
for(int i = len-1; i >= 0; i--)
{
int j = 1 & (val >> i);
if(p->next[j] == NULL) p->next[j] = new node();
p = p->next[j];
}
}
int trie_query(node *root, int val)
{
node *p = root;
int ans = 0;
for(int i = len-1; i >= 0; i--)
{
int j = ! (1 & (val >> i));
if(p->next[j])
{
p = p->next[j];
ans |= (1<<i);
}
else p = p->next[!j];
}
return ans;
}
node* trie_merge(node *p, node *q)
{
if(! p) return q;
if(! q) return p;
p->next[0] = trie_merge(p->next[0], q->next[0]);
p->next[1] = trie_merge(p->next[1], q->next[1]);
free(q);
return p;
}
void trie_del(node *p)
{
for(int i = 0; i < 2; i++)
if(p->next[i]) trie_del(p->next[i]);
free(p);
}
void dfs(int v, int fa)
{
root[v] = new node();
trie_insert(root[v], a[v]);
for(int i = head[v]; ~i; i = g[i].next)
{
int u = g[i].to;
if(u == fa) continue;
dfs(u, v);
root[v] = trie_merge(root[v], root[u]);
}
for(size_t i = 0; i < vec[v].size(); i++)
ans[vec[v][i].id] = trie_query(root[v], vec[v][i].x);
}
int main()
{
int n, m;
while(~ scanf("%d%d", &n, &m))
{
init();
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
int u, x;
for(int i = 1; i <= n-1; i++)
{
scanf("%d", &x);
add_edge(x, i+1);
}
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &u, &x);
vec[u].push_back(qnode(x, i));
}
dfs(1, 0);
for(int i = 1; i <= m; i++) printf("%d\n", ans[i]);
trie_del(root[1]);
for(int i = 1; i <= n; i++) vec[i].clear();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: