hdu6191

题意

给你一棵带点权的树,每次查询 \(u\) 和 \(x\) ,求以 \(u\) 为根结点的子树上的结点与 \(x\) 异或后最大的结果。

分析

看到子树,直接上树上启发式合并,看到异或,上 \(Trie\) 。

这道题就是两个经典的题目结合了一波。

树上启发式合并处理这种需要查询整个子树的题目尤其有用,可以复用大量的信息。

离线查询后,到要查询的结点直接在 \(Trie\) \(01\) 树上跑一下即可。

先去理解一波 树上启发式合并(\(dsu \ on \ tree\)),就会发现这真是一道模板题。

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 100;
const int MX = 30;
struct Ex {
int id, x;
};
struct Trie {
int val[MAXN * 30], nxt[MAXN * 30][2], L, root;
int newnode() {
memset(nxt[L], -1, sizeof nxt[L]);
return L++;
}
void init() {
L = 0;
root = newnode();
}
void update(int x, int key) {
int now = root;
for(int i = MX; i >= 0; i--) {
int o = (x >> i) & 1;
if(nxt[now][o] == -1) nxt[now][o] = newnode();
now = nxt[now][o];
val[now] += key;
}
}
int query(int x) {
int res = 0;
int now = root;
for(int i = MX; i >= 0; i--) {
int o = (x >> i) & 1;
if(val[nxt[now][!o]]) {
now = nxt[now][!o];
res |= (1 << i);
} else {
now = nxt[now][o];
}
}
return res;
}
}trie;
vector<Ex> ex[MAXN];
int fa[MAXN], son[MAXN], dep[MAXN], siz[MAXN];
int col[MAXN];
int cnt, head[MAXN];
struct Edge {
int to, next;
}e[MAXN << 1];
void addedge(int u, int v) {
e[cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int u) {
siz[u] = 1; son[u] = 0;
for(int i = head[u]; ~i; i = e[i].next) {
if(e[i].to != fa[u]) {
fa[e[i].to] = u;
dep[e[i].to] = dep[u] + 1;
dfs(e[i].to);
if(siz[e[i].to] > siz[son[u]]) son[u] = e[i].to;
siz[u] += siz[e[i].to];
}
}
}
int n, q;
int vis[MAXN];
int ans[MAXN];
void update(int u, int key) {
trie.update(col[u], key);
for(int i = head[u]; ~i; i = e[i].next) {
if(e[i].to != fa[u] && !vis[e[i].to]) update(e[i].to, key);
}
}
void dfs1(int u, int flg) {
for(int i = head[u]; ~i; i = e[i].next) {
if(e[i].to != fa[u] && e[i].to != son[u]) dfs1(e[i].to, 1);
}
if(son[u]) {
dfs1(son[u], 0);
vis[son[u]] = 1;
}
update(u, 1);
for(int i = 0; i < ex[u].size(); i++) {
ans[ex[u][i].id] = trie.query(ex[u][i].x);
}
if(son[u]) vis[son[u]] = 0;
if(flg) {
update(u, -1);
}
} int main() {
while(~scanf("%d%d", &n, &q)) {
for(int i = 1; i <= n; i++) {
ex[i].clear();
fa[i] = son[i] = dep[i] = siz[i] = 0;
}
memset(vis, 0, sizeof vis);
memset(ans, 0, sizeof ans);
trie.init();
cnt = 0;
memset(head, -1, sizeof head);
for(int i = 1; i <= n; i++) {
scanf("%d", &col[i]);
}
for(int i = 2; i <= n; i++) {
int u;
scanf("%d", &u);
addedge(u, i);
addedge(i, u);
}
for(int i = 0; i < q; i++) {
int u, x;
scanf("%d%d", &u, &x);
ex[u].push_back(Ex{i, x});
}
dfs(1);
dfs1(1, -1);
for(int i = 0; i < q; i++) {
printf("%d\n", ans[i]);
}
}
return 0;
}

hdu6191(树上启发式合并)的更多相关文章

  1. dsu on tree 树上启发式合并 学习笔记

    近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...

  2. 树上启发式合并(dsu on tree)学习笔记

    有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...

  3. 神奇的树上启发式合并 (dsu on tree)

    参考资料 https://www.cnblogs.com/zhoushuyu/p/9069164.html https://www.cnblogs.com/candy99/p/dsuontree.ht ...

  4. Codeforces 208E - Blood Cousins(树上启发式合并)

    208E - Blood Cousins 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor.多次查询,给出 u k,问有多少个与 u 具有相同 k-ance ...

  5. Codeforces 600E - Lomsat gelral(树上启发式合并)

    600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对 ...

  6. csu1811(树上启发式合并)

    csu1811 题意 给定一棵树,每个节点有颜色,每次仅删掉第 \(i\) 条边 \((a_i, b_i)\) ,得到两颗树,问两颗树节点的颜色集合的交集. 分析 转化一下,即所求答案为每次删掉 \( ...

  7. CF EDU - E. Lomsat gelral 树上启发式合并

    学习:http://codeforces.com/blog/entry/44351 E. Lomsat gelral 题意: 给定一个以1为根节点的树,每个节点都有一个颜色,问每个节点的子树中,颜色最 ...

  8. 【CodeChef EDGEST】Edges in Spanning Trees(树链剖分+树上启发式合并)

    点此看题面 大致题意: 给你两棵\(n\)个点的树,对于第一棵树中的每条边\(e_1\),求存在多少条第二棵树中的边\(e_2\),使得第一棵树删掉\(e_1\)加上\(e_2\).第二棵树删掉\(e ...

  9. [Codeforces600E] Lomsat gelral(树上启发式合并)

    [Codeforces600E] Lomsat gelral(树上启发式合并) 题面 给出一棵N个点的树,求其所有子树内出现次数最多的颜色编号和.如果多种颜色出现次数相同,那么编号都要算进答案 N≤1 ...

随机推荐

  1. P2127 序列排序

    题目描述 小C有一个N个数的整数序列,这个序列的中的数两两不同.小C每次可以交换序列中的任意两个数,代价为这两个数之和.小C希望将整个序列升序排序,问小C需要的最小代价是多少? 输入输出格式 输入格式 ...

  2. Intel QuickAssist Technology and OpenSSL – Benchmarks and Setup Tips

    Intel QuickAssist Technology and OpenSSL – Benchmarks and Setup Tips 来源:https://www.servethehome.com ...

  3. CF#366 704D Captain America 上下界网络流

    CF上的题,就不放链接了,打开太慢,直接上题面吧: 平面上有n个点, 第 i 个点的坐标为 ($X_i ,Y_i$), 你需要把每个点染成红色或者蓝色, 染成红色的花费为 r , 染成蓝色的花费为 b ...

  4. BZOJ1982 [Spoj 2021]Moving Pebbles 【博弈论】

    题目 Moving Pebbles Two players play the following game. At the beginning of the game they start with ...

  5. 生产服务器环境最小化安装后Centos 6.5优化配置备忘

    生产服务器环境最小化安装后 Centos 6.5优化配置备忘 本文 centos 6.5 优化 的项有18处,列表如下: 1.centos6.5最小化安装后启动网卡 2.ifconfig查询IP进行S ...

  6. Eclipse CDT 调用printf/cout 控制台(console)无输出

    转摘自:http://blog.csdn.net/dj0379/article/details/6940836 症状描述: 用Eclipse调试程序,执行printf和cout函数,但是console ...

  7. AngularJs学习——实现数据绑定的三种方式

    三种方式: 方式一:<h5>{{msg}}</h5>  此方式在页面刷新的时候会闪现{{}} 方式二:<h5 ng-bind="msg">< ...

  8. javaScript中的this关键字解析

    this是JavaScript中的关键字之一,在编写程序的时候经常会用到,正确的理解和使用关键字this尤为重要.接下来,笔者就从作用域的角度粗谈下自己对this关键字的理解,希望能给到大家一些启示, ...

  9. webpack 配置学习笔记

    最简单的 webpack 配置 const path = require('path') module.exports = { entry: './app/index.js', output: { p ...

  10. C++ 头文件保护符

    头文件保护符有什么作用? 在C++中我们写头文件时经常需要#include来包含其他头文件.头文件定义的实体经常使用其他头文件的内容,有时候会出现一个头文件被多次包含进同一源文件. 例如:一个头文件中 ...