hdu多校第五场1002 (hdu6625) three arrays 字典树/dfs

题意:

给你两个序列a,b,序列c的某位是由序列a,b的此位异或得来,让你重排序列ab,找出字典序最小的序列c。

题解:

如果能找到a,b序列中完全一样的值当然最好,要是找不到,那也尽量让低位不一样。

因此,将两个序列中元素的二进制视作字符串,建字典树。

在两棵字典树上,贪心地找让当前位一样的。

每找c的一位,dfs一遍,dfs过程中剪掉已经因为构造c而用掉的子树,构造序列c。

然后爆wa。。。

我造了好几组测例,发现贪心并不能找出当前位的最优解,比如dfs到两棵字典树上的某个点,这两个节点都既有左儿子,又有右儿子,那么到底是都向左走更优,还是都向右走更优,字典树上没有这个信息。

比如数据  3  1,0,2  2,4,1  程序打死都要给出我0,4,0的结果

直到有人提醒我:“你再把c数组排个序不就行了嘛”

我:“。。。。。。”

那么,不管不顾地贪心,只要dfs到的两点都能向1的方向走,那就都向1的方向走,因为当都向1这个方向走这棵子树此次被剪掉后,以后一定能构造出都向0的方向走的最优解。

只要再把c排序一遍,就不用计较此点最优解是先构造出来的还是后构造出来的了。

#include<iostream>
#include<cstring> 
#include<algorithm>
using namespace std;
//const int MAXN=1<<30;
struct Node{
    int to[2];
    bool end;
    int size;
};
int c[100005];
struct Trie{
    Node node[31*100005];
    int nodenum;
    void init(int n){
        for(int i=0;i<=n*31;i++)memset(&node[i],0,sizeof (Node));
        nodenum=1;
    }
    void push(int n){
        int nowid=1;
        for(int i=30;i>=0;i--){
            ++node[nowid].size;
            bool t=(n>>i)&1;
            if(node[nowid].to[t]==0){
                node[nowid].to[t]=++nodenum;
                nowid=nodenum;
            }else{
                nowid=node[nowid].to[t];
            }
//            n>>=1;
        }
        ++node[nowid].size;
        node[nowid].end=1;
    }
}trie1,trie2;
int find1(){
    int id1=1,id2=1;
    int ans=0;
    int i=0;
    bool to10,to11,to20,to21;
    while(!trie1.node[id1].end && !trie2.node[id2].end){
        ans<<=1;
        --trie1.node[id1].size;
        --trie2.node[id2].size;
        to10=trie1.node[trie1.node[id1].to[0]].size>0;
        to11=trie1.node[trie1.node[id1].to[1]].size>0;
        to20=trie2.node[trie2.node[id2].to[0]].size>0;
        to21=trie2.node[trie2.node[id2].to[1]].size>0;
        if(to11 && to21){
            id1=trie1.node[id1].to[1];
            id2=trie2.node[id2].to[1];
        }else if(to10 && to20){
            id1=trie1.node[id1].to[0];
            id2=trie2.node[id2].to[0];
        }else if(to10 && to21){
            id1=trie1.node[id1].to[0];
            id2=trie2.node[id2].to[1];
            ++ans;
        }else if(to11 && to20){
            id1=trie1.node[id1].to[1];
            id2=trie2.node[id2].to[0];
            ++ans;
        }
        ++i;
    }
    --trie1.node[id1].size;
    --trie2.node[id2].size;
    return ans;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,tmp;
        scanf("%d",&n);
        trie1.init(n);trie2.init(n);
        for(int i=1;i<=n;i++){
            scanf("%d",&tmp);
            trie1.push(tmp);
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&tmp);
            trie2.push(tmp);
        }
//        for(int i=1;i<=trie1.nodenum;i++){
//            printf("%d %d %d %d\n",trie1.node[i].size,trie1.node[i].to[0],trie1.node[i].to[1],trie1.node[i].end);
//        }
        for(int i=1;i<=n;i++){
            c[i]=find1();
        }
        sort(c+1,c+1+n);
        for(int i=1;i<=n;i++){
            printf("%d",c[i]);
            if(i<n)printf(" ");
            else printf("\n");
        }
    }
}

 

posted @ 2019-08-06 17:16  Isakovsky  阅读(479)  评论(0编辑  收藏  举报