I used to think that the dictionary tree does not have much use, but recently has been met (is not the reason for too few brush questions), one of the problems is called 01 dictionary tree problem, it is used to solve the powerful weapon of XOR, usually give you an array, ask you a continuous number of XOR and the maximum is how much, Normal thinking greedy dp what will confused, but with 01 dictionary tree can be quickly resolved, the realization is also very convenient.
Paste a universal template for a 01 dictionary tree
int ch[32*max][2];
LL Val[32*max];
int sz;
void Init () {
mem (ch[0],0);
sz=1;
}
void Inser (LL a) {
int u=0;
for (int i=32;i>=0;i--) {
int c= ((a>>i) &1);
if (!ch[u][c]) {
mem (ch[sz],0);
val[sz]=0;
ch[u][c]=sz++;
}
U=CH[U][C];
}
val[u]=a;
}
ll query (ll a) {
int u=0;
for (int i=32;i>=0;i--) {
int c= ((a>>i) &1);
if (ch[u][c^1]) u=ch[u][c^1];
else u=ch[u][c];
}
return val[u];
}
The middle details can be modified by themselves, such as sometimes may delete a number, you need to record how many times the node walked, if the number is 0, do not go down, the array size should open 32 (64, if it is ll) * array element number.
Don't say much nonsense, look at the title.
HDU 4825
Topic Portal: http://acm.hdu.edu.cn/showproblem.php?pid=4825
01 Dictionary tree entry, each number is inserted into the dictionary tree, then the query can be AC.
HDU 5536
Topic Portal: http://acm.hdu.edu.cn/showproblem.php?pid=5536
with deleted 01 dictionary tree, insert each element into the dictionary tree first, then O (n2) O (n^2) The complexity of the enumeration of two add, and then temporarily remove them from the dictionary tree, and then query, and then take the maximum value of
code:
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include & lt;string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment (linker, "
/stack:102400000,102400000 ") using namespace std; #define MAX 1005 #define MAXN 6005 #define MAXNODE #define SIGMA_SIZE #define Lson l,m,rt<<1 #define Rson m+1,r,rt<<1|1 #define LRT rt<<1 #define RR T rt<<1|1 #define Middle int m= (r+l) >>1 #define LL Long Long #define Ull unsigned long long #define MEM (x,v) memset (x,v,sizeof (x)) #define LOWBIT (x) (x&-x) #define PII Pair<int,int> #define BITS (a) __builtin_popcount (a) #define MK MakE_pair #define LIMIT 10000//const int prime = 999983;
const int INF = 0X3F3F3F3F;
Const LL INFF = 0x3f3f;
Const double PI = ACOs (-1.0);
Const double inf = 1E18;
Const double EPS = 1e-8;
Const LL mod = 1e9+7;
Const ULL MX = 133333331;
/*****************************************************/inline void RI (int &x) {char C;
while (C=getchar ()) < ' 0 ' | | c> ' 9 ');
x=c-' 0 ';
while ((C=getchar ()) >= ' 0 ' && c<= ' 9 ') x= (x<<3) + (x<<1) +c-' 0 ';
}/*****************************************************/int ch[32*max][2];
LL Val[32*max];
int Num[32*max];
int sz;
LL B[max];
void init () {mem (ch[0],0);
Sz=1;
} void Inser (LL a) {int u=0;
for (int i=32;i>=0;i--) {int c= ((a>>i) &1);
if (!ch[u][c]) {mem (ch[sz],0);
val[sz]=0;
num[sz]=0;
ch[u][c]=sz++;
} U=ch[u][c];
num[u]++;
} val[u]=a; } VOID Update (LL a,int d) {int u=0;
for (int i=32;i>=0;i--) {int c= ((a>>i) &1);
U=CH[U][C];
Num[u]+=d;
}} LL query (ll a) {int u=0;
for (int i=32;i>=0;i--) {int c= ((a>>i) &1);
if (Ch[u][c^1]&&num[ch[u][c^1]]) u=ch[u][c^1];
else U=ch[u][c];
} return A^val[u];
} int main () {int t,kase=0;
cin>>t;
while (t--) {int n;
scanf ("%d", &n);
Init ();
for (int i=1;i<=n;i++) {scanf ("%i64d", &b[i]);
Inser (B[i]);
}//kase++;
printf ("Case #%d:\n", Kase);
LL maxn=0;
for (int i=1;i<=n;i++) {for (int j=1;j<=n;j++) {if (i==j) continue;
Update (b[i],-1); update (B[J],-1);
Maxn=max (Maxn,query (b[i]+b[j));
Update (b[i],1); update (b[j],1);
}} cout<<maxn<<endl; } return 0; }
Bzoj 4260
Topic Portal: http://www.lydsy.com/JudgeOnline/problem.php?id=4260
lets you find two disjoint contiguous intervals in an array of n. Make two interval respectively of the difference or sum after the maximum
anyway see continuous interval xor and maximum, I will only a routine, is 01 dictionary tree, first is to go over the prefix XOR, and at the same time Dp[i] dp[i] to I, the front of the interval XOR and maximum is how much, and then backwards to the suffix XOR and , Ans=max (Ans,query (Suf[i]) +dp[i−1]) Ans=max (Ans,query (Suf[i]) +dp[i-1]) can, and this problem will not explode int, in fact, as if the above question will not explode int, But the full ll will be the MLE
Code:
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include & lt;string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment (linker, "
/stack:102400000,102400000 ") using namespace std; #define MAX 400005 #define MAXN 6005 #define MAXNODE #define SIGMA_SIZE #define Lson l,m,rt<<1 #define Rson m+1,r,rt<<1|1 #define LRT rt<<1 #define RRT rt<<1|1 #define Middle int m= (r+l) >>1 #define LL Long Long #define Ull unsigned long long #define MEM (x,v) memset (x,v,sizeof (x)) #define LOWBIT (x) (x&-x) #define PII Pair<int,int> #define BITS (a) __builtin_popcount (a) #define MKMake_pair #define LIMIT 10000//const int prime = 999983;
const int INF = 0X3F3F3F3F;
Const LL INFF = 0x3f3f;
Const double PI = ACOs (-1.0);
Const double inf = 1E18;
Const double EPS = 1e-8;
Const LL mod = 1e9+7;
Const ULL MX = 133333331;
/*****************************************************/inline void RI (int &x) {char C;
while (C=getchar ()) < ' 0 ' | | c> ' 9 ');
x=c-' 0 ';
while ((C=getchar ()) >= ' 0 ' && c<= ' 9 ') x= (x<<3) + (x<<1) +c-' 0 ';
}/*****************************************************/int Pre[max];
int Suf[max];
int A[max];
int Dp[max];
int ch[32*max][2];
int Val[32*max];
int sz;
void Init () {sz=1;
MEM (ch[0],0);
} void Inser (int a) {int u=0;
for (int i=31;i>=0;i--) {int c= ((a>>i) &1);
if (!ch[u][c]) {mem (ch[sz],0);
val[sz]=0;
ch[u][c]=sz++;
} U=ch[u][c];
} val[u]=a; } int Query (iNT a) {int u=0;
for (int i=31;i>=0;i--) {int c= ((a>>i) &1);
if (ch[u][c^1]) u=ch[u][c^1];
else U=ch[u][c];
} return val[u]^a;
} int main () {int n;
cin>>n;
Init ();
for (int i=1;i<=n;i++) scanf ("%d", &a[i]);
pre[0]=suf[n+1]=0;
for (int i=1;i<=n;i++) pre[i]=pre[i-1]^a[i];
for (int i=n;i>0;i--) suf[i]=suf[i+1]^a[i];
MEM (dp,0);
Inser (Pre[0]);
for (int i=1;i<=n;i++) {Dp[i]=max (Dp[i-1],query (Pre[i]));
Inser (Pre[i]);
} init ();
int maxn=0;
Inser (suf[n+1]);
for (int i=n;i>0;i--) {Maxn=max (Maxn,query (Suf[i]) +dp[i-1]);
Inser (Suf[i]);
} cout<<maxn<<endl;
return 0; }
POJ 3764
Topic Portal: http://poj.org/problem?id=3764
This is the largest difference or path on the tree, but it is also the same routine, in the Dfs, from the root to the current node of the XOR, go to 01 dictionary tree query , find a path and the current path XOR and maximum, this found is absolutely two connected, because you go to the 01 dictionary tree, is from the root to the current node of the XOR and
Code:
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include & lt;string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment (linker, "
/stack:102400000,102400000 ") using namespace std; #define MAX 100005 #define MAXN 6005 #define MAXNODE #define SIGMA_SIZE #define Lson l,m,rt<<1 #define Rson m+1,r,rt<<1|1 #define LRT rt<<1 #define RRT rt<<1|1 #define Middle int m= (r+l) >>1 #define LL Long Long #define Ull unsigned long long #define MEM (x,v) memset (x,v,sizeof (x)) #define LOWBIT (x) (x&-x) #define PII Pair<int,int> #define BITS (a) __builtin_popcount (a) #define MKMake_pair #define LIMIT 10000//const int prime = 999983;
const int INF = 0X3F3F3F3F;
Const LL INFF = 0x3f3f;
Const double PI = ACOs (-1.0);
Const double inf = 1E18;
Const double EPS = 1e-8;
Const LL mod = 1e9+7;
Const ULL MX = 133333331;
/*****************************************************/inline void RI (int &x) {char C;
while (C=getchar ()) < ' 0 ' | | c> ' 9 ');
x=c-' 0 ';
while ((C=getchar ()) >= ' 0 ' && c<= ' 9 ') x= (x<<3) + (x<<1) +c-' 0 ';
}/*****************************************************/int ch[32*max][2];
int Val[32*max];
int sz; struct edge{int v,next,c;}
EDGE[MAX*2];
int Head[max];
int tot;
int ans;
void Init () {sz=1;
MEM (ch[0],0);
MEM (head,-1);
tot=0;
ans=0;
} void Add_edge (int a,int b,int c) {edge[tot]= (edge) {b,head[a],c};
head[a]=tot++;
} void Inser (int a) {int u=0;
for (int i=31;i>=0;i--) {int c= ((a>>i) &1);