zoukankan      html  css  js  c++  java
  • HDU 6625 (01字典树)

    题意:
    给定两个长为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
  • 相关阅读:
    Blue:贪心,单调队列
    建设城市(city):组合数,容斥原理
    [考试反思]0809NOIP模拟测试15:解剖
    [考试反思]0807NOIP模拟测试14:承认
    [考试反思]阶段性总结:NOIP模拟测试7~13
    [考试反思]0805NOIP模拟测试13:窒息
    [考试反思]0803NOIP模拟测试12:偿还
    [态度]关于博客
    差异:后缀数组(wzz模板理解),决策单调性
    [考试反思]0801NOIP模拟测试11
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/11571473.html
Copyright © 2011-2022 走看看