點我看題
題意:給出一顆樹,每棵樹上有n個結點,每個結點對應乙個值,有m組查詢操作,查詢在從x到y的這條路徑上與z進行異或的最大值。
分析:可持久化字典樹的模板題
這個題以01字典樹為基礎,如果不是很了解01字典樹的話,可以看看acdream1063,這題題解。
話說回來,如果我們要查詢數x與某個數異或的最大值,我們應該盡量選擇高位與x的高位相反的一些數。
舉個栗子,我們要求5與某個數異或的最大值,假設可選的數不超過15,5的二進位制為0101,因為可選的數不超過15,所以我們只要考慮後四位,
首先看最高位(第四位)存不存在等於1的數,存在的話,一直往低位走,最終可以得到結果。
這個題就要對每個結點都建一棵trie樹(感覺根主席樹有點像噢,主席樹是對每個結點建線段樹
建trie樹的時候,我們用乙個陣列sz記錄字典樹對應結點字首的數量,如果v是u的子節點,且v的權值是010,u的權值為011,假設u已經加到樹中,那麼在加v的時候,發現字首01的數量已經是1了,那我們只要在這個基礎上加1即可,也就是繼承了父節點對它的影響,但是對於010來說是乙個新的數,我們要新建乙個結點然後更新他的sz,其餘和父節點一致就好。
當我們去查詢每一位都取反的x時,只關心每一位是否對應存在。也就是想知道u到v這條路上有沒有滿足條件的存在。
設pre=lca(u,v),我們就只要判斷f(u)+f(v)-2×f(pre)是否大於0就好,大於0的話,就加上1>>i。
/*可持久化字典樹*/
#include#include#include#include#include#includeusing namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e5+10;//原樹結點
const int maxv = 16;//每顆字典樹的深度
const int maxnode = 2e6;//字典樹的結點個數,16*1e5=1600000
int n,q;
int a[maxn];
vectorg[maxn];
//字典樹
int tot;//記錄字典樹的總結點數
int root[maxn];//記錄字典樹的根節點
int f[maxv+2][maxn];//嘻嘻嘻嘻f[i][v]指的是結點v向上跳2^i次後得到的結點值
int sz[maxnode];//記錄字首和
int dep[maxn];//記錄結點深度
int ch[maxnode][2];//字典樹兒子結點
void init()
int newnode()
void insert( int u, int fa, int val)
rtu = ch[rtu][id];//往下走
rtf = ch[rtf][id];
sz[rtu]++;
}}//遍歷原樹中的n個結點,對每個結點建立01字典樹
void dfs( int u, int fa)
}//倍增lca
//求u和v的最近公共祖先
int lca( int u, int v)
int query( int u, int v, int val)
{ int f = lca(u,v);//求u,v的最近公共祖先
int res = a[f]^val;
int rtu = root[u], rtv = root[v], rtf = root[f];//轉化到字典樹中去
int ret = 0;
for( int i = maxv-1; i >= 0; i--)
{int id = (val>>i)&1;
if( sz[ch[rtu][!id]]+sz[ch[rtv][!id]]-2*sz[ch[rtf][!id]] > 0)//滿足這個條件
{ret += 1<
可持久化Trie HDU4757 Tree
恩,剛學了一發可持久化trie樹,其實挺簡單的。反正可持久化資料結構都乙個樣嘛,動態加點就好了。還是寫一篇部落格給自己看吧。因為樹上的路徑嘛,肯定要想到把路徑分成兩部分,x lca x,y 和 y lca x,y 這就相當與兩塊區間,然後求單點異或最大值,自然就想到可持久化了唄。想想你怎麼用可持久化...
可持久化Treap
本來是想寫一點題的,但是hfu最近讓我改鍵盤指法,原來都是亂打 手速蠻快就是錯的多 剛開始練手法真的煩躁,像我這種從來不用小指頭的 就寫個學習筆記吧.非教程向,只是懂了後寫點隨筆,練成指法說不定能來填坑.可持久化treap首先是基於非旋轉式treap的,如果要旋轉的話那麼就會破壞父子關係導致無法可持...
可持久化Treap
可持久化treap本質上市乙個二叉平衡樹,若不對其規則進行修改,中序遍歷後得出的序列是遞增的。void maintain o 計算結點o的size int lowcount key 比key所在位置小1 int uppercount key key所在的位置,如果有多個相同的key,選位置最大的 i...