2019 Multi-University Training Contest 5 1002 three arrays 01字典樹+貪心

題意:給你長度都爲n的兩個數組a和b,定義ci=ai xor bi,讓你任意排列兩個數組的順序,讓ci的字典序最小

題解:其實就是貪心的思想,建立兩個01字典樹,如果兩個字典樹有相同的邊就走相同的邊,沒有就走不同的邊,但是沒法保證誰先到後到,所以還得對c數組排一下序

代碼借鑑了這裏的dfs,後來學長對我說直接跑n次,每次從上往下一條邊一條邊的往下刮也行。後來想了一下,其實dfs也不是個樹形的,因爲四個轉移條件只能成立其中一個,所以這個dfs也是線性的。。。其實就是類似一個for循環的東西,所以直接寫for循環也行。這裏的dfs好處就在於每走一遍能刮下來很多條邊,所以寫起來比較方便

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mem(s) memset(s, 0, sizeof(s))
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const int maxn = 1e5+5;
const int mod = 998244353;
struct Trie01{
    int tot;
    int val[32*maxn];
    int ch[32*maxn][2],cnt[32*maxn];
    void init(){
        tot=1;
        ch[0][0]=ch[0][1]=0;
        cnt[0]=0;
    }
    void insert(int x){
        int u=0;
        for(int i=30;i>=0;i--){
            int v=(x>>i)&1;
            if(!ch[u][v]){
                ch[tot][0]=ch[tot][1]=0;
                val[tot]=0;cnt[tot]=0;
                ch[u][v]=tot++;
            }
            u=ch[u][v];cnt[u]++;
        }
        val[u]=x;
    }
    int query(int x){
        int u=0;
        for(int i=30;i>=0;i--){
            int v=(x>>i)&1;
            if(ch[u][v^1])u=ch[u][v^1];
            else u=ch[u][v];
        }
        return val[u];
    }
}A,B;
vector<pair<int,int> >ans;
void dfs(int p1,int p2,int x){
    int e=min(A.cnt[p1],B.cnt[p2]);
    A.cnt[p1]-=e;B.cnt[p2]-=e;
    if(A.val[p1]||B.val[p2]){
        ans.push_back(make_pair(x,e));
        return ;
    }
    int a1=A.ch[p1][0],a2=A.ch[p1][1],b1=B.ch[p2][0],b2=B.ch[p2][1];
    if(A.cnt[a1]&&B.cnt[b1]){
        dfs(a1,b1,x<<1);
    }
    if(A.cnt[a2]&&B.cnt[b2]){
        dfs(a2,b2,x<<1);
    }
    if(A.cnt[a1]&&B.cnt[b2]){
        dfs(a1,b2,(x<<1)+1);
    }
    if(A.cnt[a2]&&B.cnt[b1]){
        dfs(a2,b1,(x<<1)+1);
    }
}
int main() 
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        A.init();B.init();ans.clear();
        for(int i=1;i<=n;i++){
            int tmp;
            scanf("%d",&tmp);
            A.insert(tmp);
        }
        for(int i=1;i<=n;i++){
            int tmp;
            scanf("%d",&tmp);
            B.insert(tmp);
        }
        dfs(0,0,0);
        sort(ans.begin(),ans.end());
        for(int i=0;i<ans.size();i++){
            for(int j=0;j<ans[i].second;j++){
                printf("%d",ans[i].first);
                if(j<ans[i].second-1)printf(" ");
            }
            if(i<ans.size()-1)printf(" ");
        }
        printf("\n");
    }
    return 0;
}

 

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