题目:hdu6625
题意:给你两个数组a,b,要求你重排a,b使c[i]=a[i]^b[i]得到的c数组字典序最小
分析:根据贪心思想,每次都要求得a[i]^b[i]都最小才能保证字典序最小。
有两种方法:
方法一:对a,b两个数组建两颗字典树,每次同时遍历两棵字典树,如果都为0或都为1就走,否则没有办法只有一个走0一个走1,此时对答案产生贡献,每次找出来的最后排个序就ok
Ac code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n;
int a[maxn],b[maxn];
struct Trie
{
int ch[31*maxn][2],tot,num[31*maxn],val[31*maxn];
void init(int n)
{
tot=0;
for(int i=0; i<=30*n; i++)
{
num[i]=val[i]=0;
for(int j=0; j<2; j++)
ch[i][j]=0;
}
}
void insert(int d)
{
int rt=0;
for(int i=30; i>=0; --i)
{
int id=(d>>i)&1;
if(!ch[rt][id])
ch[rt][id]=++tot;
rt=ch[rt][id];
num[rt]++;
}
val[rt]=d;
}
int query(int d)
{
int rt=0;
for(int i=30; i>=0; --i)
{
int id=(d>>i)&1;
if(ch[rt][id]&&num[ch[rt][id]]) rt=ch[rt][id];
else rt=ch[rt][id^1];
}
return val[rt];
}
void del(int d)
{
int rt=0;
for(int i=30; i>=0; --i)
{
int id=(d>>i)&1;
rt=ch[rt][id];
num[rt]--;
}
}
} A,B;
int fnd()
{
int p=0,q=0,ans=0;
for(int i=30;i>=0;--i)
{
int id=0;
if(A.ch[p][id]&&A.num[A.ch[p][id]]&&B.ch[q][id]&&B.num[B.ch[q][id]]) p=A.ch[p][id],q=B.ch[q][id];
else if(A.ch[p][id^1]&&A.num[A.ch[p][id^1]]&&B.ch[q][id^1]&&B.num[B.ch[q][id^1]]) p=A.ch[p][id^1],q=B.ch[q][id^1];
else if(A.ch[p][id]&&A.num[A.ch[p][id]]) ans|=(1<<i),p=A.ch[p][id],q=B.ch[q][id^1];
else ans|=(1<<i),q=B.ch[q][id],p=A.ch[p][id^1];
}
A.del(A.val[p]);
B.del(B.val[q]);
return ans;
}
vector<int>ans;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans.clear();
scanf("%d",&n);
A.init(n),B.init(n);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]),A.insert(a[i]);
for(int i=1; i<=n; i++)
scanf("%d",&b[i]),B.insert(b[i]);
for(int i=0; i<n; i++)
ans.push_back(fnd());
sort(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++)
printf("%d%c",ans[i],i==ans.size()-1?'\n':' ');
}
return 0;
}
方法二:还有一种就是题解给的方法,确实挺nb的。
Ac code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n;
int a[maxn],b[maxn];
struct Trie
{
int ch[31*maxn][2],tot,num[31*maxn],val[31*maxn];
void init(int n)
{
tot=0;
for(int i=0; i<=30*n; i++)
{
num[i]=val[i]=0;
for(int j=0; j<2; j++)
ch[i][j]=0;
}
}
void insert(int d)
{
int rt=0;
for(int i=30; i>=0; --i)
{
int id=(d>>i)&1;
if(!ch[rt][id])
ch[rt][id]=++tot;
rt=ch[rt][id];
num[rt]++;
}
val[rt]=d;
}
int query(int d)
{
int rt=0;
for(int i=30; i>=0; --i)
{
int id=(d>>i)&1;
if(ch[rt][id]&&num[ch[rt][id]]) rt=ch[rt][id];
else rt=ch[rt][id^1];
}
return val[rt];
}
void del(int d)
{
int rt=0;
for(int i=30; i>=0; --i)
{
int id=(d>>i)&1;
rt=ch[rt][id];
num[rt]--;
}
}
int fnd()
{
int rt=0;
for(int i=30;i>=0;--i)
{
int id=0;
if(ch[rt][id]&&num[ch[rt][id]]) rt=ch[rt][id];
else if(ch[rt][id^1]&&num[ch[rt][id^1]]) rt=ch[rt][id^1];
else return -1;
}
return val[rt];
}
} A,B;
vector<int>ans;
void solve()///flag=1表示u为A中的元素
{
bool flag=1;
stack<int>s;
s.push(a[1]);
while(!s.empty())
{
int u=s.top();
s.pop();
if(flag)
{
int v=B.query(u);
if(!s.empty()&&v==s.top())
{
ans.push_back(u^v);
B.del(v);
A.del(u);
s.pop();
}
else if(ans.size()==n-1)
{
ans.push_back(u^v);
break;
}
else s.push(u),s.push(v),flag=!flag;
}
else
{
int v=A.query(u);
if(!s.empty()&&v==s.top())
{
ans.push_back(u^v);
A.del(v);
B.del(u);
s.pop();
}
else if(ans.size()==n-1)
{
ans.push_back(u^v);
break;
}
else s.push(u),s.push(v),flag=!flag;
}
if(s.empty()){
int d=A.fnd();
if(d!=-1) s.push(d);
flag=!flag;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans.clear();
scanf("%d",&n);
A.init(n),B.init(n);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]),A.insert(a[i]);
for(int i=1; i<=n; i++)
scanf("%d",&b[i]),B.insert(b[i]);
solve();
sort(ans.begin(),ans.end());
//cout<<ans.size();
for(int i=0; i<ans.size(); i++)
printf("%d%c",ans[i],i==ans.size()-1?'\n':' ');
}
return 0;
}