hdu5536 Chip Factory (01字典樹刪除操作)
Problem Description
John is a manager of a CPU chip factory, the factory produces lots of chips everyday. To manage large amounts of products, every processor has a serial number. More specifically, the factory produces n chips today, the i-th chip produced this day has a serial number si.
At the end of the day, he packages all the chips produced this day, and send it to wholesalers. More specially, he writes a checksum number on the package, this checksum is defined as below:
which i,j,k are three different integers between 1 and n. And ⊕ is symbol of bitwise XOR.
Can you help John calculate the checksum number of today?
Input
The first line of input contains an integer T indicating the total number of test cases.
The first line of each test case is an integer n, indicating the number of chips produced today. The next line has n integers s1,s2,..,sn, separated with single space, indicating serial number of each chip.
1≤T≤1000
3≤n≤1000
0≤si≤109
There are at most 10 testcases with n>100
Output
For each test case, please output an integer indicating the checksum number in a line.
Sample Input
2
3
1 2 3
3
100 200 300
Sample Output
6
400
大致題意:給你n個數,讓你從中選擇三個不同的數,將其中兩個數相加後異或上第三個數,使得結果最大,問最大結果為多少。
思路:先將這n個數建立成一顆01字典樹,然後O(n^2)的去列舉兩個不同的數,將其從字典樹中刪除,然後再查詢此時異或最大值,然後再向字典樹中加入這兩個數。
程式碼如下
1.陣列
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define LL long long
#define ULL unsigned long long
const int MAXN=32*1005;
struct Trie
{
int ch[2];
int size;
}T[MAXN];
int root=1,tot=1;
void add(int x)
{
int p=root;
T[p].size++;
for(int i=31;i>=0;i--)
{
int k=(x>>i)&1;
if(!T[p].ch[k]) T[p].ch[k]=++tot;
p=T[p].ch[k];
T[p].size++;
}
}
void Delete(int x)
{
int p=root;
T[p].size--;
for(int i=31;i>=0;i--)
{
int k=(x>>i)&1;
p=T[p].ch[k];
T[p].size--;
}
}
int query(int x)
{
int ans=0;
int p=root;
for(int i=31;i>=0;i--)
{
int k=(x>>i)&1;
if(T[p].ch[k^1]&&T[T[p].ch[k^1]].size)
ans^=(1<<i),p=T[p].ch[k^1];
else
p=T[p].ch[k];
}
return ans;
}
void init()
{
for(int i=1;i<=tot;i++)
T[i].ch[0]=T[i].ch[1]=T[i].size=0;
tot=1;
}
int a[1005];
int main()
{
int T;
scanf("%d",&T);
int n,num;
for(int cas=1;cas<=T;cas++)
{
init();
int ans=-1;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(a[i]);
}
for(int i=1;i<=n;i++)
{
Delete(a[i]);
for(int j=i+1;j<=n;j++)
{
Delete(a[j]);
ans=max(ans,query(a[i]+a[j]));
add(a[j]);
}
add(a[i]);
}
printf("%d\n",ans);
}
return 0;
}
2.指標
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define LL long long
#define ULL unsigned long long
struct node
{
int size;
node *Next[2];
};
void add(node *head,int num)
{
node *p=head;
p->size++;
for(int i=31;i>=0;i--)
{
int k=(num>>i)&1;
if(p->Next[k]==NULL)
{
node *q=new node();
p->Next[k]=q;
}
p=p->Next[k];
p->size++;
}
}
void Delete(node *head,int num)
{
node *p=head;
p->size--;
for(int i=31;i>=0;i--)
{
int k=(num>>i)&1;
p=p->Next[k];
p->size--;
}
}
int query(node *head,int num)
{
node *p=head;
int x=0;
for(int i=31;i>=0;i--)
{
int k=(num>>i)&1;
if(p->Next[k^1]&&p->Next[k^1]->size)
p=p->Next[k^1],x^=(1<<i);
else
p=p->Next[k];
}
return x;
}
int a[1005];
int main()
{
int T;
scanf("%d",&T);
int n,num;
for(int cas=1;cas<=T;cas++)
{
node *head=new node();
int ans=-1;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(head,a[i]);
}
for(int i=1;i<=n;i++)
{
Delete(head,a[i]);
for(int j=i+1;j<=n;j++)
{
Delete(head,a[j]);
ans=max(ans,query(head,a[i]+a[j]));
add(head,a[j]);
}
add(head,a[i]);
}
printf("%d\n",ans);
}
return 0;
}