貌似可以解决一些跟异或相关的问题?

1 #include<vector> 2 #include<cstdio> 3 #include<iostream> 4 #define pb push_back 5 #define nc getchar 6 #define read(x) scanf("%d", &x) 7 using namespace std; 8 struct Edge{int v, w, n;} E[200005]; 9 int n, d[100005], head[100005], ec; 10 inline void aE(int u, int v, int w) { 11 E[++ec] = (Edge){v, w, head[u]}; head[u] = ec; 12 E[++ec] = (Edge){u, w, head[v]}; head[v] = ec; 13 } 14 void dfs(int u, int f, int w) { 15 d[u] = w; for (int i = head[u]; i; i = E[i].n) 16 if (E[i].v != f) dfs(E[i].v, u, E[i].w ^ w); 17 } 18 struct Node { 19 Node *ch[2]; 20 } Tnull, *null = &Tnull, *root; 21 Node mem[2000000], *C; 22 inline Node* newNode() { 23 C->ch[0] = C->ch[1] = null; return C++; 24 } 25 void insert(int x) { 26 Node *u = root; 27 for (int i = 31; ~i; --i) { 28 int c = (x >> i) & 1; 29 if (u->ch[c] == null) u->ch[c] = newNode(); 30 u = u->ch[c]; 31 } 32 } 33 int find(int x) { 34 Node *u = root; int res = 0; 35 for (int i = 31; ~i; --i) { 36 int c = !((x >> i) & 1); 37 if (u->ch[c] == null) u = u->ch[!c]; 38 else u = u->ch[c], res += 1 << i; 39 } return res; 40 } 41 void solve() { 42 for (int i = 1; i <= n; ++i) insert(d[i]); int res = 0; 43 for (int i = 1; i <= n; ++i) res = max(res, find(d[i])); 44 printf("%d\n", res); 45 } 46 int main() { 47 while (~scanf("%d", &n)) { 48 for (int u, v, w, i = 1; i < n; ++i) 49 read(u), read(v), read(w), aE(u + 1, v + 1, w); 50 for (int i = head[1]; i; i = E[i].n) dfs(E[i].v, 1, E[i].w); 51 C = mem; root = newNode(); solve(); 52 for (int i = 1; i <= n; ++i) d[i] = 0; 53 for (int i = 1; i <= n; ++i) head[i] = 0; 54 ec = 0; 55 } 56 return 0; 57 }
这题咱用vector存边T了。
记f(i)为从根节点出发到i点时边权的异或和。
根据异或的性质,u-v这条路径的异或和就是f(u) xor f(v)。
把所有的f(i)都插入一个01trie上,然后枚举一个f(i),再贪心另一个。

#include<cstdio> #include<iostream> using namespace std; inline char nc() { static char b[1<<12],*s=b,*t=b; return s==t&&(t=(s=b)+fread(b,1,1<<12,stdin),s==t)?-1:*s++; } inline void read(int &x) { char b = nc(); x = 0; for (; !isdigit(b); b = nc()); for (; isdigit(b); b = nc()) x = x * 10 + b - ‘0‘; } inline int read() { char b = nc(); for (; !isalpha(b); b = nc()); return b == ‘A‘; } struct Node { Node *ch[2]; int v; } Tnull, *null = &Tnull; Node mem[24000010], *rt[600010], *C = mem; inline Node* newNode() { C->ch[0] = C->ch[1] = null; C->v = 0; return C++; } int n, m, xr; void insert(int x, Node *u, Node *p) { for (int i = 24; ~i; --i) { int c = (x >> i) & 1; if (u->ch[c] == null) u->ch[c] = newNode(); u->ch[!c] = p->ch[!c]; u = u->ch[c]; p = p->ch[c]; u->v = p->v + 1; } } int query(int x, Node *L, Node *R) { int res = 0; for (int i = 24; ~i; --i) { int c = !((x >> i) & 1); if (R->ch[c]->v - L->ch[c]->v > 0) res += 1 << i; else c = !c; // R->ch[c]->v - L->ch[c]->v > 0 ? res += 1 << i : c = !c; R = R->ch[c], L = L->ch[c]; } return res; } int main() { null->ch[0] = null->ch[1] = null; read(n); read(m); ++n; rt[0] = newNode(); rt[1] = newNode(); insert(0, rt[1], rt[0]); for (int i = 2, t; i <= n; ++i) read(t), xr ^= t, rt[i] = newNode(), insert(xr, rt[i], rt[i-1]); for (int x, l, r, i = 0; i < m; ++i) { if (read()) { read(x); xr ^= x; ++n; rt[n] = newNode(); insert(xr, rt[n], rt[n-1]); } else { read(l); read(r); read(x); printf("%d\n", query(xr ^ x, rt[l-1], rt[r])); } } return 0; }
记 f_n = a_1 xor a_2 xor ... xor a_n
即求 x xor f_n xor f_{p-1} 的最大值。
注意到 x xor f_n 为一定值,所以我们只需要在只存[l-1, r-1]这段区间值的trie上贪心就行。