hdu4757 Tree
来源:互联网 发布:linux退出vi编辑 编辑:程序博客网 时间:2024/06/11 11:33
可持久化Trie,比赛的时候一直在想不到怎么样才可以做减法,赛后才想清楚。
首先异或最大就是在字典树上找它的按位取反,首先满足高位。
对每个节点维护一个Trie,维护的是它到根所有路过的节点的权值,维护Trie的时候同时维护一下子树的叶子节点个数。
对于每一个询问先倍增求出LCA,再由三个节点的权值来计算某子树的叶子节点个数,判断能不能走到某个儿子,如果某棵子树没有叶子节点就意味着不能走。
说的比较抽象,看代码比较好懂吧。。大概
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <cstdlib>#include <cmath>#include <cctype>#include <queue>#include <stack>#include <map>#include <set>#include <list>#define pb push_back#define mp make_pair#define fi first#define se second//#pragma comment(linker, "/STACK:16777216")using namespace std;typedef long long LL;typedef unsigned long long ULL;#define N 100010#define M 2000000int u[M][2] , v[M] , cnt;int n , m , a[N] , L[N] , f[17][N] , pre[N] , mcnt;struct edge{ int x , next;}e[N << 1];int str[20];int root[N];int newnode(){ memset(u[cnt] , 0 , sizeof(u[cnt])); v[cnt] = 0; return cnt ++;}void insert(int x , int y , int val){ x = root[x] , y = root[y]; for (int i = 0 ; i < 16 ; ++ i) { int c = val >> (16 - i - 1) & 1; if (!u[x][c]) u[x][c] = newnode() , u[x][!c] = u[y][!c] , v[u[x][c]] = v[u[y][c]]; x = u[x][c] , y = u[y][c]; ++ v[x]; }}int query(int x , int y , int z , int val){ int ans = 0 , res = a[z] ^ val; x = root[x] , y = root[y] , z = root[z]; for (int i = 0 ; i < 16 ; ++ i) { int c = !(val >> (16 - i - 1) & 1); if (v[u[x][c]] + v[u[y][c]] - v[u[z][c]] - v[u[z][c]] > 0) ans |= 1 << (16 - i - 1); else c = !c; x = u[x][c] , y = u[y][c] , z = u[z][c]; } return max(ans , res);}void dfs(int x , int fa){ f[0][x] = fa , L[x] = L[fa] + 1 ; root[x] = newnode(); insert(x , fa , a[x]); for (int i = pre[x] ; ~i ; i = e[i].next) if (e[i].x != fa) dfs(e[i].x , x);}int LCA(int x , int y){ if (L[x] > L[y]) swap(x , y); for (int i = 16 ; i >= 0 ; -- i) if (L[y] - L[x] >= 1 << i) y = f[i][y]; if (x == y) return y; for (int i = 16 ; i >= 0 ; -- i) if (f[i][x] && f[i][x] != f[i][y]) x = f[i][x] , y = f[i][y]; return f[0][x];}void work(){ int i , j , x , y , z , w; memset(pre , -1 , sizeof(pre)); mcnt = 0 , cnt = 1; for (i = 1 ; i <= n ; ++ i) scanf("%d",&a[i]); for (i = 1 ; i < n ; ++ i) { scanf("%d%d",&x,&y); e[mcnt].x = y , e[mcnt].next = pre[x] , pre[x] = mcnt ++; e[mcnt].x = x , e[mcnt].next = pre[y] , pre[y] = mcnt ++; } memset(f , 0 , sizeof(f)); dfs(1 , 0); for (j = 1 ; 1 << j < n ; ++ j) for (i = 1 ; i <= n ; ++ i) f[j][i] = f[j - 1][f[j - 1][i]]; while (m --) { scanf("%d%d%d",&x,&y,&w); z = LCA(x , y); printf("%d\n" , query(x , y , z , w)); }}int main(){ freopen("~input.txt" , "r" , stdin); while (~scanf("%d%d",&n,&m)) work(); return 0;}
- hdu4757 Tree
- Tree HDU4757
- [HDU4757][可持久化Trie][LCA]Tree[好题]
- hdu4757(LCA+可持久化字典树)
- Tree
- tree
- tree
- TREE
- Tree
- Tree
- tree
- tree
- tree
- tree
- tree
- tree
- Tree
- Tree
- 发一下自己用的gvimrc 文件吧... 以后备着用
- 链表笔试面试题 .
- mysql获取自增id最大值四种方法
- 51.和为n连续正数序列
- zigbee 万能遥控器 裸机发送和协议栈发送
- hdu4757 Tree
- zigbee cc2530地址空间 layout 和flash操作
- 字符串匹配的KMP算法
- zigbee 协议栈的时钟和定时器分频
- zigbee bind, ZDO_RegisterForZDOMsg, zcl_registerForMsg
- templete_BigNum(大数模版)
- zigbee 空中消息溯源
- ios应用程序的生命周期
- 美化DataGridView控件