HDU 6625 (01字典树)

谁都会走 提交于 2019-11-30 07:15:30

题意:
给定两个长为n的数组a和b;
重新排列a和b,生成数组c,c[i]=a[i] xor b[i];
输出字典序最小的c数组。

分析:
将a中的数插入一颗01字典树a中;
将b中的数插入一颗01字典树b中;
在trie树上查找n次,每次同时在a和b中下移一层;
if 能同时走0,则同时走0;
else if 能同时走1,则同时走1;
else if 树a能走0&&树b能走1,则a走0、b走1;
else if 树a能走1&&树b能走0,则a走1、b走0;
else 向c中插入一个新数为这两个节点的异或值;
最后对c排序。
复杂度O(T*n*30)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
typedef long long LL;
struct Trie01{

int ch[35 * maxn][2];
int cnt[35*maxn];
int node_cnt;
inline void init(){
    node_cnt = 1;
    memset(ch[0],0,sizeof(ch[0]));

}
inline void Insert(LL x){
    int cur = 0;
    for(int i = 30;i >= 0;--i){
        int idx = (x >> i) & 1;
        if(!ch[cur][idx]){
            memset(ch[node_cnt],0,sizeof(ch[node_cnt]));
            ch[cur][idx] = node_cnt;
            cnt[node_cnt++]=0;
        }
        cur = ch[cur][idx];
        cnt[cur]++;
    }
}
}t1,t2;
vector<int> ans;
void solve(int N){
    int u1,u2;
    while(N--) {
        u1 = u2 = 0;
        int x = 0;
        for(int p = 30; p >= 0; p--) {

            if(t1.cnt[t1.ch[u1][0]] && t2.cnt[t2.ch[u2][0]]) {
                t1.cnt[t1.ch[u1][0]]--;
                t2.cnt[t2.ch[u2][0]]--;
                u1 = t1.ch[u1][0]; u2 = t2.ch[u2][0];
            } else if(t1.cnt[t1.ch[u1][1]] && t2.cnt[t2.ch[u2][1]]) {
                t1.cnt[t1.ch[u1][1]]--;
                t2.cnt[t2.ch[u2][1]]--;
                u1 = t1.ch[u1][1]; u2 = t2.ch[u2][1];
            } else if(t1.cnt[t1.ch[u1][0]] && t2.cnt[t2.ch[u2][1]]) {
                t1.cnt[t1.ch[u1][0]]--;
                t2.cnt[t2.ch[u2][1]]--;
                u1 = t1.ch[u1][0]; u2 = t2.ch[u2][1];
                x ^= (1 << p);
            } else {
                t1.cnt[t1.ch[u1][1]]--;
                t2.cnt[t2.ch[u2][0]]--;
                u1 = t1.ch[u1][1]; u2 = t2.ch[u2][0];
                x ^= (1 << p);
            }

        }
        ans.push_back(x);
    }
    return ;
}
int main(){
    int _;scanf("%d",&_);
    while(_--){
        int n;scanf("%d",&n);
        t1.init(),t2.init();
        for(int i=1;i<=n;i++){
            int x;scanf("%d",&x);
            t1.Insert(x);
        }
        for(int i=1;i<=n;i++){
            int x;scanf("%d",&x);
            t2.Insert(x);
        }
        ans.clear();
        solve(n);
        sort(ans.begin(),ans.end());
        printf("%d",ans[0]);
        for(int i=1;i<ans.size();i++)
        {
            printf(" %d",ans[i]);
        }puts("");
    }
}
View Code

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!