HDU6625 01字典樹亂搞

題意:給你兩個數組a和b,讓你安排a和b的順序使得a數組與b數組一一對應得到的異或數組c字典序最小

思路:建01字典樹暴力跑最優匹配即可,借鑑標程思想寫了一份AC代碼,將兩個數組建到一顆字典樹上,用num數組維護當前節點是否可用,這樣便使得刪除操作非常容易實現,在匹配的時候利用dfs的性質去暴力匹配即可,複雜度nlogn

代碼如下:

#include<bits/stdc++.h>
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<int> 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<<i;
        }
    }
    return res;
}
int find(int x,int d)
{
    int now=0;
    int res=0;
    for(int i=29;i>=0;i--)
    {
        int op=(x>>i)&1;
        if(tree[now][op]&&num[tree[now][op]][d])
        {
            now=tree[now][op];
            res|=op<<i;
        }
        else
        {
            now=tree[now][op^1];
            res|=(op^1)<<i;
        }
    }
    return res;
}
void del(int x,int d)
{
    int now=0;
    for(int i=29;i>=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()<n)
        {
            int x=get();
            dfs(x,0,-1);
        }
        sort(ans.begin(),ans.end());
        for(int i=0;i<ans.size();i++)
        {
            if(i) printf(" ");
            printf("%d",ans[i]);
        }
        printf("\n");
        for(int i=0;i<=cnt;i++)
            tree[i][0]=tree[i][1]=0;
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章