對於題目給出的兩個查詢,我們我可以將它這樣轉換:
對於操作一,用dfs序將乙個子樹轉化為一段連續的區間,然後根據dfs序建立乙個trie樹,那麼查詢乙個子樹即為查詢一段區間
對於操作二,根據根到結點的路徑建立乙個trie樹,同樣也可以轉化為乙個區間查詢
於是就可以建兩個trie樹,分別對應兩個操作
結合**理解
#include#include#includeusing namespace std;
const int n = 4e5 + 50, m = 32 * n;
int tr1[m][2], root1[n], tot1, siz[n];
int w[n], n, q, maxn[m], id[n], it[n];
int head[n], ver[n], net[n], idx, cnt, root2[n];
int tr2[m][2], dep[n], fa[n][25], maxd[m], tot2;
void add(int a, int b)
void insert1(int p, int q, int i, int k)
int v = w[it[k]] >> i & 1;
if (q)
tr1[p][!v] = tr1[q][!v];
tr1[p][v] = ++tot1;
insert1(tr1[p][v], tr1[q][v], i - 1, k);
maxn[p] = max(maxn[tr1[p][0]], maxn[tr1[p][1]]);
return;
}void insert2(int p, int q, int i, int k)
int v = w[k] >> i & 1;
if (q)
tr2[p][!v] = tr2[q][!v];
tr2[p][v] = ++tot2;
insert2(tr2[p][v], tr2[q][v], i - 1, k);
maxd[p] = max(maxd[tr2[p][0]], maxd[tr2[p][1]]);
return;
}int query1(int p, int v, int l)
return v ^ w[it[maxn[p]]];
}int query2(int p, int v, int l)
return res;
}void dfs(int u, int f)
}int lca(int x, int y)
int main()
dfs(1, 0);
for (int i = 1; i <= n; i++)
while (q--)
else
}return 0;
}
TJOI2018簡要題解
按照時間軸建一棵線段樹即可,複雜度為 o m log m include define n 100005 define ll long long define getchar nc using namespace std inline char nc inline ll read while ch ...
BZOJ5338 TJOI2018 異或 題解
現在有一顆以1為根節點的由n個節點組成的樹,樹上每個節點上都有乙個權值vi。現在有q 次操作,操作如下 1 x y 查詢節點x的子樹中與y異或結果的最大值 2 x y z 查詢路徑x到y上點與z異或結果最大值 hdu4757 tree 題解 別的不想多說了,出原題不怕被罵嗎 include incl...
TJOI2018 數學計算
如果採取暴力的做法,那麼乘起來會炸longlong,除非寫個高精。再考慮乘一下逆元呢,顯然也不行,模數不一定為質數。這道題的關鍵點在於這句話,對於每乙個型別1的操作至多會被除一次 這句話的最基本的告訴了我們每次得到的答案一定是乙個整數 其次,這句話保證了可以應用線段樹解決這個問題 如果除的操作可能會...