当前位置: 代码迷 >> 综合 >> HDU5536 Chip Factory Trie(01字典树)
  详细解决方案

HDU5536 Chip Factory Trie(01字典树)

热度:57   发布时间:2023-12-06 19:39:17.0
题意:

给出 n(3n1000) n(3≤n≤1000)个数字,求 max(si+sj)?sk max(si+sj)?sk,而且 i,j,k i,j,k互不相等。

分析:

把每个数字看成一个 01 01字符串插入倒Trie树中去,枚举 i i j j,然后把 si si sj sj从Trie树中删去。
然后在Trie树中贪心找到能与 si+sj si+sj异或得到的最大值。
具体匹配的过程中是这样的,首先看树中最高位能否异或得到 1 1
能的话就往能的那个方向走,否则往另外一个方向走。

另外删除操作是这样实现的,我们每个节点记录一个 val val值。
插入时对所有经过节点的 val val值加 1 1,删除就将对应节点的 val val值减 1 1
在树上匹配的时候就只走那些 val

val值为正的节点。


#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;
const int maxnode = 1e5+10;
int sz;//总共节点个数
int s[maxn], ch[maxnode][2], val[maxnode];
void init()
{sz = 1;memset(ch[0], 0, sizeof(ch[0]));
}
//d=1表示插入,d=-1表示删除
void update(int v, int d)
{int u = 0;for(int i = 30; i >= 0; i--){int c = (v >> i) & 1;if(!ch[u][c]){memset(ch[sz], 0, sizeof(ch[sz]));val[sz] = 0;ch[u][c] = sz++;}u = ch[u][c];val[u] += d;}
}
int match(int v)
{int ans = 0, u = 0;for(int i = 30; i >= 0; i--){int c = (v >> i) & 1;if(ch[u][c^1] && val[ch[u][c^1]]){ans |= (1 << i);u = ch[u][c^1];}elseu = ch[u][c];}return ans;
}
int main()
{int n, T;scanf("%d", &T);while(T--){init();scanf("%d", &n);for(int i = 1; i <= n; i++){scanf("%d", &s[i]);update(s[i], 1);}int ans = (s[1] + s[2]) ^ s[3];for(int i = 1; i <= n; i++){update(s[i], -1);for(int j = i + 1; j <= n; j++){update(s[j], -1);int t = match(s[i] + s[j]);ans = max(ans, t);update(s[j], 1);}update(s[i], 1);}printf("%d\n", ans);}return 0;
}


动态分配节点的写法:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;
const int N = 2;
int s[maxn];
struct tree
{int val;tree *nxt[N];tree(){for(int i = 0; i < N; i++)nxt[i] = NULL;val = 0;}
}*root;
int a[33];
void ch(int x)
{memset(a, 0, sizeof(a));int len = 0;while(x){a[len++] = x % 2;x /= 2;}
}
void Insert(int x)
{ch(x);int len = 31;tree *p = root;while(len >= 0){int id = a[len];if(p -> nxt[id] == NULL){tree *temp = new tree;p -> nxt[id] = temp;}p = p -> nxt[id];p -> val++;len--;}
}
int query(int x)
{ch(x);tree *p = root;for(int i = 0; i < 31; i++)a[i] ^= 1;int len = 31;int ans = 0;while(len >= 0){int id = a[len];if(p -> nxt[id] == NULL || p -> nxt[id] -> val == 0)id ^= 1;if(id)ans +=  1 << len;p = p -> nxt[id];len--;}return ans ^ x;
}
void del(int x)
{ch(x);int len = 31;tree *p = root;while(len >= 0){int id = a[len];p -> nxt[id] -> val--;p = p -> nxt[id];len--;}
}
void fre(tree *tmp)
{for(int i = 0; i < N; i++)if(tmp -> nxt[i])fre(tmp -> nxt[i]);delete(tmp);
}
int main()
{int n, T;scanf("%d", &T);while(T--){scanf("%d", &n);root = new tree;for(int i = 0; i < n; i++){scanf("%d", &s[i]);Insert(s[i]);}int ans = 0;for(int i = 0; i < n; i++){del(s[i]);for(int j = i + 1; j < n; j++){del(s[j]);ans = max(ans, query(s[i] + s[j]));Insert(s[j]);}Insert(s[i]);}printf("%d\n", ans);fre(root);}return 0;
}


  相关解决方案