HDU 6191 2017广西邀请赛Query on A Tree:可持久化01字典树(区间抑或最大值查询)
来源:互联网 发布:sass 22.0 for mac 编辑:程序博客网 时间:2024/05/01 13:49
题意:给出一棵n(<=1e5)个点的树,每个点有一个权,询问q(<=qe5)次,每次询问(nod,val),计算出以nod为根的子树上的所有点,权抑或val的最大值是多少。
题解:基本上是个板子题吧。直接讲方法了。。直接上DFS序+可持久化01字典树就行了。可持久化01字典树可以用32步查得一个区间内某个数字和val抑或得到的最大答案,那么DFS序一下就可以把子树搞成区间。然后完美解决。
可持久化01字典树:可以理解成在字典树的每个节点上弄了个前缀和一样的东西吧,重点在空间复用。每个字典树节点增加sum域,记录前边数字中有多少个数字走到这个节点。每次加入一个新的数字,都开一个“全新”的字典树,把每个树的根都记下来。这个新的字典树包括了之前加入的所有数字,也包括当前数字,但是这样超级浪费空间,怎么办呢,我们知道 加入一个新的数字,和上一棵树最多只会有32个点不同。那么新树和上一个树不变的点就直接用上一棵树的就行了(两个树相同的部分重合起来,不需要新开点来存了),把新的点的sum给更新了就行了。
查询:查询区间[ l , r ]时,同时查root[ l-1 ] 和 root[ r ]这两棵树,同时往下走,如果sum不同, 说明[ l , r ]区间内的某个数字出现在这条链路上,那么就可以往这个方向走。然后取抑或最大操作和普通01字典树无异,都是贪心的高位能取不同就不同,否则取相同(相同和不同必然可以取一个,要不然岂不是说明这个区间内没有数字了。。。)。
Flag:01字典树什么的不可能写WA的hhhhhh(除非是能把x写成y的lowB葫芦娃)
以及博主最近沉迷冒险岛2。。。。。。没救了
Code:
#include<bits/stdc++.h>using namespace std;const int MAX = 1e5+100;int bas[35];int nxt[MAX<<5][2];int root[MAX];int sum[MAX<<5];int n,q;vector<int>E[MAX];int st[MAX],en[MAX],rk[MAX];int a[MAX];int cnt;int tot;void sheet(){bas[0]=1;for (int i=1;i<=30;i++){bas[i] = bas[i-1]<<1;}}void init(){for (int i=0;i<=n;i++){E[i].clear();}cnt =tot=0;memset(nxt[0],0,sizeof nxt[0]);}void input(){for (int i=1;i<=n;i++){scanf("%d",a+i);}for (int u=2;u<=n;u++){int v;scanf("%d",&v);E[u].push_back(v);E[v].push_back(u);}}void dfs(int node ,int father ){st[node] = ++tot;rk[tot] = node;for (int des:E[node]){if(des==father){continue;}dfs(des,node);}en[node] = tot;}int create(){cnt++;memset(nxt[cnt],0,sizeof nxt[cnt]);return cnt;}int insert(int rt,int val){int y = ++cnt;int x = rt;int res = y;for (int i=30;i>=0;i--){sum[y] = sum[x]+1;nxt[y][0] = nxt[x][0];nxt[y][1] = nxt[x][1];int t = val&bas[i];t>>=i;nxt[y][t] = create();y = nxt[y][t];x = nxt[x][t];}sum[y] = sum[x]+1;return res;}int query(int l,int r,int val){int res =0;int x = l;int y = r;for (int i=30;i>=0;i--){int t = val&bas[i];t>>=i;if (sum[nxt[y][!t]]-sum[nxt[x][!t]]){y = nxt[y][!t];x = nxt[x][!t];res+=bas[i];}else{y = nxt[y][t];x = nxt[x][t];} }return res;}void solve(){dfs(1,0);for (int i=1;i<=n;i++){root[i] = insert(root[i-1],a[rk[i]]);}while (q--){int nod,x;scanf("%d%d",&nod,&x);printf("%d\n",query(root[st[nod]-1],root[en[nod]],x));}}int main(){sheet();while (scanf("%d%d",&n,&q)!=EOF){init();input();solve();} return 0;}
- HDU 6191 2017广西邀请赛Query on A Tree:可持久化01字典树(区间抑或最大值查询)
- 2017 icpc广西邀请赛 K.Query on A Tree (hdu 6191)可持久化字典树
- 2017广西邀请赛 Query on A Tree(可持久化字典树)
- HDU 6191 && 2017广西邀请赛:Query on A Tree(字典树启发式合并)
- 2017 广西邀请赛&& hdu 6191 Query on A Tree(字典树启发式合并)
- hdu 6191 Query on A Tree(字典树启发式合并(动态建树) 可持久化字典树+dfs序)
- HDU 6191 Query on A Tree [可持久化字典树]
- HDU 6191 Query on A Tree ( DFS序 + 可持久化字典树 )
- HDU 6191 Query on A Tree (dfs序+可持久化01Trie)
- 2017ACM/ICPC广西邀请赛 K- Query on A Tree trie树合并
- HDU 6191 Query on A Tree 可持久化trie + dfs建树 || 启发式合并trie
- [hdu 6191 Query on A Tree] 字典树启发式合并
- CS Course (广西2017邀请赛) 用线段树区间查询
- hdu 4757 Tree(可持久化字典树)
- hdu-4757-Tree-树链剖分+可持久化字典树
- Hdu-4757 Tree(可持久化字典树)
- hdu 4757 Tree(可持久化字典树)
- 2017广西邀请赛/hdu
- Log4j 日志文件存放位置设置
- 单链表环的系列问题,及图解
- 2017盛大游戏2017前端工程师校招笔试题总结
- Maven学习笔记
- Ionic如何创建自定义展开标题组件
- HDU 6191 2017广西邀请赛Query on A Tree:可持久化01字典树(区间抑或最大值查询)
- mongodb索引
- Pat(A) 1089. Insert or Merge (25)
- 数据挖掘:如何通过百度地图API抓取物体周边地理位置信息
- 逆元
- 安卓模拟器Android studio中VT-x is disabled in BIOS问题。
- Linux,centOS更改默认打开页面巨详细教程
- StringBuffer类
- 九度 1482 玛雅人的密码