題解 TJOI2018 異或

2022-06-20 20:18:13 字數 1416 閱讀 6192

對於題目給出的兩個查詢,我們我可以將它這樣轉換:

對於操作一,用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的操作至多會被除一次 這句話的最基本的告訴了我們每次得到的答案一定是乙個整數 其次,這句話保證了可以應用線段樹解決這個問題 如果除的操作可能會...