可持久化Trie HDU4757 Tree

2022-05-08 05:09:11 字數 1479 閱讀 4028

恩,剛學了一發可持久化trie樹,其實挺簡單的。。

反正可持久化資料結構都乙個樣嘛,動態加點就好了。

還是寫一篇部落格給自己看吧。

因為樹上的路徑嘛,肯定要想到把路徑分成兩部分,x->lca(x,y) 和 y->lca(x,y) 。 這就相當與兩塊區間,然後求單點異或最大值,自然就想到可持久化了唄。(想想你怎麼用可持久化線段樹求區間第k大(小)就好了)。只需要按照遍歷順序把點權以二進位制的形式插入trie樹。新的版本從它的父親節點的版本那繼承就好了。

(p:我用倍增求的lca)

插入的時候把路徑上的每個點的cnt+1,這樣處理,你用x的版本減去lca(x,y)的版本就可以得到了x->lca(x,y)路徑上有哪些點的點權啦。

然後根據trie樹貪心就好,盡量使每一位都和z不同。

因為trie樹存的是二進位制嘛,如果,z的某一位是1的話,你就看有沒有這一位是0的數,如果有就走ch[0],不然你就只能走ch[1]了。。

這樣滿足高位最大,答案就最優,所以你的trie樹肯定從高位存到低位啦,最高位設為17就好,反正最大才16。

emmmmm... 然後感覺就沒什麼了,不過有個細節。

重要的事說三遍,不要問我wa了多少次。。

#include#include#include#include#define ll long long

#define pch putchar

#define gch getchar

#define mem(k) memset(k,0,sizeof k)

using namespace std;

const int maxn=100000+5;

const int maxm=100000+5;

int n,m;

int cnt,root[maxn];

struct treetree[maxn*2*20+maxm*20];//空間你就估摸著開吧,每次插入新增17個點。

int head[maxn],cou,a[maxn],d[maxn],p[maxn][20];

struct roadroad[maxn<<1];

inline int insert(int x,int pre,int pos)

inline void add_edge(int x,int y)

inline void dfs(int now,int fa)

for(int i=head[now];i!=-1;i=road[i].next)

}inline int lca(int x,int y)

} return p[x][0];

}inline int ask(int now,int pre,int x)

inline int query(int x,int y,int z)

int main()

dfs(1,0);

for(int i=1;i<=m;++i)

} return 0;

}

hdu4757 (可持久化字典樹 LCA)

給一棵樹,每個節點有權值。每次詢問要求回答乙個值異或某條路徑上的乙個點的最大值。我們可以對每乙個點開乙個字典樹,記錄從這個點到根的路徑上的所有數,然後求兩點的lca,然後把路徑分成左端點到lca的路和右端點到lca的路來做。includeusing namespace std const int m...

HDU 4757 樹鏈剖分 可持久化字典樹

題目鏈結 思路 對於這種詢問樹的路徑的題,第一反應就是樹鏈剖分,但與多個給定值異或後的最大值卻沒有辦法去高效維護。考慮另外的思路。有關異或的資料結構,自然會想到01字典樹,聯絡乙個經典問題 求乙個數與乙個數集中的某個數異或的最大值 而對於此題,每乙個詢問相當於給定了乙個數集,只不過其中的數是一條路徑...

可持久化Treap

本來是想寫一點題的,但是hfu最近讓我改鍵盤指法,原來都是亂打 手速蠻快就是錯的多 剛開始練手法真的煩躁,像我這種從來不用小指頭的 就寫個學習筆記吧.非教程向,只是懂了後寫點隨筆,練成指法說不定能來填坑.可持久化treap首先是基於非旋轉式treap的,如果要旋轉的話那麼就會破壞父子關係導致無法可持...