hdu6191(树上启发式合并)
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(树上启发式合并)的更多相关文章
- dsu on tree 树上启发式合并 学习笔记
近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...
- 树上启发式合并(dsu on tree)学习笔记
有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...
- 神奇的树上启发式合并 (dsu on tree)
参考资料 https://www.cnblogs.com/zhoushuyu/p/9069164.html https://www.cnblogs.com/candy99/p/dsuontree.ht ...
- Codeforces 208E - Blood Cousins(树上启发式合并)
208E - Blood Cousins 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor.多次查询,给出 u k,问有多少个与 u 具有相同 k-ance ...
- Codeforces 600E - Lomsat gelral(树上启发式合并)
600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对 ...
- csu1811(树上启发式合并)
csu1811 题意 给定一棵树,每个节点有颜色,每次仅删掉第 \(i\) 条边 \((a_i, b_i)\) ,得到两颗树,问两颗树节点的颜色集合的交集. 分析 转化一下,即所求答案为每次删掉 \( ...
- CF EDU - E. Lomsat gelral 树上启发式合并
学习:http://codeforces.com/blog/entry/44351 E. Lomsat gelral 题意: 给定一个以1为根节点的树,每个节点都有一个颜色,问每个节点的子树中,颜色最 ...
- 【CodeChef EDGEST】Edges in Spanning Trees(树链剖分+树上启发式合并)
点此看题面 大致题意: 给你两棵\(n\)个点的树,对于第一棵树中的每条边\(e_1\),求存在多少条第二棵树中的边\(e_2\),使得第一棵树删掉\(e_1\)加上\(e_2\).第二棵树删掉\(e ...
- [Codeforces600E] Lomsat gelral(树上启发式合并)
[Codeforces600E] Lomsat gelral(树上启发式合并) 题面 给出一棵N个点的树,求其所有子树内出现次数最多的颜色编号和.如果多种颜色出现次数相同,那么编号都要算进答案 N≤1 ...
随机推荐
- 【题解】SDOI2009学校食堂
不知道有没有人跟我有一样的感觉……实际上很多的状压DP都不难,然而调到心碎……这题题面看起来很长,还有混合的‘位运算’来吓唬人(实际上就是异或而已).但实际上只要仔细阅读,发现也是一道水水的裸题. 首 ...
- [POI2007]ATR-Tourist Attractions
题目大意:一个无向图,从$1$到$n$,要求必须经过$2,3,\dots,k+1$,给出一些限制关系,要求在经过$v\leq k+1$之前必须经过$u\leq k+1$,求最短路 题解:预处理出$1\ ...
- Mybatis缓存机制及mybatis的各个组成部分
Mybatis 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 ...
- Linux产生背景
By francis_hao Oct 26,2016 很久很久以前,大概在1965年左右,由贝尔实验室(Bell).麻省理工学院(MIT)及通用电气公司(GE)共同发起了一个叫做Multics的项目, ...
- UVA10480:Sabotage(最小割+输出)
Sabotage 题目链接:https://vjudge.net/problem/UVA-10480 Description: The regime of a small but wealthy di ...
- Codeforces Round #525 (Div. 2) F. Ehab and a weird weight formula
F. Ehab and a weird weight formula 题目链接:https://codeforces.com/contest/1088/problem/F 题意: 给出一颗点有权值的树 ...
- 安卓和html的互相调用
1.写html和安卓布局 <Button android:id="@+id/btn" android:layout_width="wrap_content" ...
- AngularJs学习——模拟用户登录的简单操作
效果截图:
- Spring--环境配置
目录 1.1 Spring jar包下载 1.2 Hello World 参考资料 1.1 Spring jar包下载 (1)进入官网http://repo.spring.io(或者 http://m ...
- Linux基础(1)
一.Linux的安装及相关配置 1.VMware Workstation安装CentOS7.0 图文版 详细步骤可以看连接:http://blog.csdn.net/alex_my/article/d ...