hdu6191(广西邀请赛K)
来源:互联网 发布:mac局域网通信软件 编辑:程序博客网 时间:2024/04/25 08:43
题目链接
题意是给一棵树,每个点有点权,然后每次询问给一个子树和一个x,问子树上面所有的点中异或x的最大值是多少。
这个题目可以离线用字典树合并的方式,从叶子往根去合并,也可以用dfs序直接把子树转化为区间上的问题,然后用可持续化trie树去做。
可持续化trie树本质其实和主席树的建树方式差不多,动态建树且每一次新增一条链。然后当询问某一个子树的时候,通过dfs序把它变成一个区间,然后就是01字典树上面走走。从高到底看看这一位有没有与x相反的bit位,如果有还要判断是否在L到R的区间上。
#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<set>#include<map>#include<time.h>#include<cstdio>#include<vector>#include<list>#include<stack>#include<queue>#include<iostream>#include<stdlib.h>using namespace std;#define LONG long longconst int INF=0x3f3f3f3f;const LONG MOD=1e9+ 7;const double PI=acos(-1.0);#define clrI(x) memset(x,-1,sizeof(x))#define clr0(x) memset(x,0,sizeof x)#define clr1(x) memset(x,INF,sizeof x)#define clr2(x) memset(x,-INF,sizeof x)#define EPS 1e-10#define lson l , mid , rt<< 1#define rson mid + 1 ,r , (rt<<1)+1#define root 1, n , 1const int MAXN = 140000 ;int L[MAXN + 50 ] , R[MAXN + 50] ;int TOT = 0;int Root[MAXN + 50 ] ;struct Trie{ int next[2] ; int sum ; Init() { clrI(next) ; sum = 0 ; }}trie[ (MAXN << 6 )+ (MAXN << 5)];struct Edge{ int next ,to ;}edge[200100] ;int head[MAXN] ;int tot = 0 ;int cnt = 0 ;int V[MAXN] ;int Rank[MAXN] ;void Init(){ tot = 0 ; clrI(head) ; cnt = 0 ; TOT = 0;}void Add(int u ,int v){ edge[++tot].to = v; edge[tot].next = head[u] ; head[u] = tot ;}void Dfs(int pre ,int u){ L[u] = ++cnt ; Rank[cnt] = u ; for(int i = head[u] ;~i ; i = edge[i].next) { int v =edge[i].to ; if(v == pre ) continue ; Dfs(u , v) ; } R[u] = cnt ;}void Build(int x){ int now = 0 ; for(int i = 31 ; i >= 0 ; -- i) { int p = (( x>>i ) & 1) ; if(trie[now].next[p] == -1) { trie[now].next[p] = ++TOT ; trie[TOT].Init() ; } now = trie[now].next[p] ; trie[now].sum ; }}int Insert(int x , int rt , int d ){ TOT ++ ; int now = TOT ; trie[now] = trie[rt] ; if( d== -1) return now ; int p = ( (x>>d) & 1 ) ; trie[now].next[p] = Insert( x , trie[now].next[p],d-1 ) ; trie[trie[now].next[p]].sum ++ ; return now ;}int Que(int x ,int L_rt,int R_rt){ int res = 0 ; for(int i = 31 ; i >= 0 ; -- i) { int p = ((x>>i)&1) ; if(trie[R_rt].next[p^1] == -1) { R_rt = trie[R_rt] .next[p] ; L_rt = trie[L_rt] .next[p] ; } else { int tmp1 = trie[R_rt].next[p^1] ; int tmp2 = trie[L_rt].next[p^1 ] ; if(trie[tmp1].sum - trie[tmp2].sum > 0) { res += (1<<i) ; R_rt = tmp1 ; L_rt = tmp2 ; } else { R_rt = trie[R_rt].next[p] ; L_rt = trie[L_rt].next[p] ; } } } return res ;}int main(){ int n , q ; while(cin >> n >> q) { Init() ; for(int i = 1; i <= n ; ++ i) scanf("%d",&V[i]) ; int tmp ; f or(int i= 1;i < n ; ++i) { scanf("%d",&tmp ) ; Add(i + 1, tmp ) ; Add(tmp , i + 1 ) ; } Dfs( -1 , 1) ; for(int i= 1;i<= n ; ++ i) trie[0].Init() ; for(int i = 1 ;i<= n ; ++ i) Build(V[Rank[ i ] ]) ; Root[0] = 0 ; for(int i = 1;i<= n ; ++ i) Root[i] = Insert( V[Rank[i]] , Root[i-1 ] , 31) ; int u , x; int l ,r ; int ans = 0 ; while(q --) { scanf("%d%d",&u,&x) ; l = L[u] - 1; r = R[u] ; ans = Que(x , Root[l] , Root[r]) ; cout<<ans<<endl ; } for(int i = 0 ;i<= TOT ;++ i) { clrI( trie[i].next ) ; trie[i].sum = 0 ; } } return 0 ;}
阅读全文
1 0
- hdu6191(广西邀请赛K)
- [广西邀请赛
- 2017广西邀请赛/hdu
- 2017 icpc广西邀请赛 K.Query on A Tree (hdu 6191)可持久化字典树
- 2017ACM/ICPC广西邀请赛 K- Query on A Tree trie树合并
- 广西 2017 邀请赛 CS Course
- 2017年广西邀请赛总结
- 2017ACM/ICPC广西邀请赛
- 2017广西邀请赛补题
- 广西2017邀请赛 Problem E CS Course
- 广西 2017 邀请赛 Duizi and Shunzi
- HDU 6186 && 2017广西邀请赛:CS Course
- 2017ACM/ICPC广西邀请赛-重现赛
- 2017ACM/ICPC广西邀请赛总结
- 2017ACM-ICPC全国邀请赛(广西)
- 广西邀请赛PD(dp+矩阵加速)
- 2017ACM/ICPC广西邀请赛-重现赛
- 广西2017邀请赛 E: CS Course &,|,^ 运算
- Hibernate框架(二)
- Codeforces Round #431 Div2
- 轻松使用ESP8266
- Java泛型概述
- 缩略图thumbnail
- hdu6191(广西邀请赛K)
- npm: 2.15.1 should be >= 3.0.0 npm install express operation not permitted
- SQL:整数类型小结
- 广播的种类
- hbase坑一:hbase shell启动报错
- Linux下openresty+redis 的权限控制
- SharedPreferences导航页 第二次直接跳转
- jpython的使用(Java调用python脚本)
- Android基础总结七:SeekBar的使用