HDU6625 01字典树乱搞

题意:给你两个数组a和b,让你安排a和b的顺序使得a数组与b数组一一对应得到的异或数组c字典序最小

思路:建01字典树暴力跑最优匹配即可,借鉴标程思想写了一份AC代码,将两个数组建到一颗字典树上,用num数组维护当前节点是否可用,这样便使得删除操作非常容易实现,在匹配的时候利用dfs的性质去暴力匹配即可,复杂度nlogn

代码如下:

#include
using namespace std;
const int maxn=1e5+5;
int tree[31*maxn][2];
int a[maxn],b[maxn];
int num[31*maxn][2];
int cnt;
vector ans;
void insert(int x,int d)
{
    int now=0;
    for(int i=29;i>=0;i--)
    {
        int op=(x>>i)&1;
        if(tree[now][op]==0)
            tree[now][op]=++cnt;
        now=tree[now][op];
        num[now][d]++;
    }
}
int get()
{
    int now=0;
    int res=0;
    for(int i=29;i>=0;i--)
    {
        if(tree[now][0]&&num[tree[now][0]][0])
            now=tree[now][0];
        else
        {
            now=tree[now][1];
            res|=1<=0;i--)
    {
        int op=(x>>i)&1;
        if(tree[now][op]&&num[tree[now][op]][d])
        {
            now=tree[now][op];
            res|=op<=0;i--)
    {
        int op=(x>>i)&1;
        now=tree[now][op];
        --num[now][d];
    }
}
bool dfs(int x,int d,int pre)
{
    while(1)
    {
        int y=find(x,d^1);
        if(y==pre)
        {
            ans.push_back(x^y);
            del(x,d);
            del(y,d^1);
            return true;
        }
        if(dfs(y,d^1,x))
            return false;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ans.clear();
        cnt=0;
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            insert(a[i],0);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&b[i]);
            insert(b[i],1);
        }
        while(ans.size()

 

你可能感兴趣的:(acm)