CF923C Perfect Security

大兔子大兔子 提交于 2020-02-04 21:39:28

一、题目

点此看题

题目描述

给你两个长度为nn的数组a,ba,b,你可以把bb数组任意排列后对应位和aa数组异或,求字典序最小的异或结果。

二、解法

很容易看出的贪心,枚举aa中的每一个值,找到和bb未选中的值异或最小的结果,按顺序输出即可。

可以用一个数据结构维护bb数组,异或相关问题我们可以使用trietrie树,我们把bb数组拿去建trietrie树,然后把aa中的每个值拿去匹配,trietrie树上的每个点维护一个子树中还未被选中个数,就很容易做了。

注意把每一个值拆成长度为3030的二进制串,从高位到低位做即可,时间复杂度O(nlogn)O(n\log n)

#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 300005;
const int M = 30*N;
int read()
{
 int x=0,flag=1;char c;
 while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
 while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
 return x*flag;
}
int n,a[M],b[31];
struct trie
{
    int cnt,ch[M][2],val[M];
    trie() {cnt=1;}
    void add(int x)
    {
        int p=1;
        for(int i=30;i>=0;i--)
        {
            int c=(x>>i)&1;
            if(!ch[p][c]) ch[p][c]=++cnt;
            p=ch[p][c];val[p]++;
        }
    }
    void solve(int x)
    {
        int p=1,ans=0;
        for(int i=30;i>=0;i--)
        {
            int c=(x>>i)&1;
            if(!val[ch[p][c]]) c^=1;
            p=ch[p][c];val[p]--;
            ans=(ans<<1)+c;
        }
        printf("%d ",ans^x);
    }
}tr;
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    for(int i=1;i<=n;i++)
        tr.add(read());
    for(int i=1;i<=n;i++)
        tr.solve(a[i]);
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!