zoukankan      html  css  js  c++  java
  • 异或数组

    也许更好的阅读体验

    (mathcal{Description})

    给你两个长度为(n)的数组(a,b)
    你需要把(a,b)两个数组分别按某种方式排序
    然后令(c_i=a_i xor b_i),你要使(c)的字典序最小
    请输出(c)这个数组
    (nleq200000 a_i,b_ileq 2^{30})

    (mathcal{Solution})

    (a,b)这两个数组的数分别放到一个(01Trie)树里面
    并记下每个点的位置有多少串经过
    然后考虑构造(c)
    两个(Trie)树一起开始跑,从(2^{30})开始考虑
    先考虑两边异或起来为(0)的情况,再考虑两边异或起来为(1)
    这样跑完(2^0)的点后就可以得到一个(c),并且一定是最优的

    接下来则是技巧的问题
    如果对(c)的每个元素单独算,即每次都重新匹配一次,尽管我将其改为(bfs)并且进行了些优化,但仍然会(T(50pts))

    考虑一遍(dfs)处理所有的答案
    在每个位置都先考虑异或起来为(0),再考虑异或起来为(1)的情况
    然后每次将改点经过的串的个数减(1)
    这样就可以过了

    (mathcal{Code})

    50分代码

    /*******************************
    Author:Morning_Glory
    LANG:C++
    Created Time:2019年09月16日 星期一 09时45分46秒
    *******************************/
    #include <cstdio>
    #include <fstream>
    #include <algorithm>
    using namespace std;
    const int len = 30;
    const int maxn = 3000006;
    //{{{cin
    struct IO{
    	template<typename T>
    	IO & operator>>(T&res){
    		res=0;
    		bool flag=false;
    		char ch;
    		while((ch=getchar())>'9'||ch<'0')	flag|=ch=='-';
    		while(ch>='0'&&ch<='9')	res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
    		if (flag)	res=~res+1;
    		return *this;
    	}
    }cin;
    //}}}
    int n,a,b,h,t,k,cnt;
    int mi[len+1],res[maxn];
    int q[3][maxn];//q[0] -> 哪一位 q[1] -> na q[2] -> nb
    struct Trie{
    	int tot=1;
    	int num[maxn];
    	int ch[maxn][2];
    	//{{{insert
    	void insert (int s)
    	{
    		int now=1;
    		for (int i=len;i>=0;--i){
    			bool to=s&mi[i];
    			if (!ch[now][to]) ch[now][to]=++tot;
    			now=ch[now][to];
    			++num[now];
    		}
    	}
    	//}}}
    }A,B;
    //{{{dfs
    void dfs(int x,int y,int S,int k)
    {
    	if(x) --A.num[x],--B.num[y];
    	if(k<0) {	res[++cnt]=S;return;}
    	while(A.num[A.ch[x][0]]&&B.num[B.ch[y][0]])  dfs(A.ch[x][0],B.ch[y][0],S,k-1);
    	while(A.num[A.ch[x][1]]&&B.num[B.ch[y][1]])  dfs(A.ch[x][1],B.ch[y][1],S,k-1);
    	while(A.num[A.ch[x][0]]&&B.num[B.ch[y][1]])  dfs(A.ch[x][0],B.ch[y][1],S|mi[k],k-1);
    	while(A.num[A.ch[x][1]]&&B.num[B.ch[y][0]])  dfs(A.ch[x][1],B.ch[y][0],S|mi[k],k-1);
    }
    //}}}
    int main()
    {
    	mi[0]=1;
    	for (int i=1;i<=len;++i)	mi[i]=mi[i-1]<<1;
    	cin>>n;
    	for (int i=1;i<=n;++i)	cin>>a,A.insert(a);
    	for (int i=1;i<=n;++i)	cin>>b,B.insert(b);
    	dfs(1,1,0,30);
    	sort(res+1,res+n+1);
    	for (int i=1;i<=n;++i)	printf("%d ",res[i]);
    	return 0;
    }
    
    

    100分代码

    /*******************************
    Author:Morning_Glory
    LANG:C++
    Created Time:2019年09月16日 星期一 09时45分46秒
    *******************************/
    #include <cstdio>
    #include <fstream>
    #include <algorithm>
    using namespace std;
    const int len = 30;
    const int maxn = 3000006;
    //{{{cin
    struct IO{
    	template<typename T>
    	IO & operator>>(T&res){
    		res=0;
    		bool flag=false;
    		char ch;
    		while((ch=getchar())>'9'||ch<'0')	flag|=ch=='-';
    		while(ch>='0'&&ch<='9')	res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
    		if (flag)	res=~res+1;
    		return *this;
    	}
    }cin;
    //}}}
    int n,a,b,h,t,k,cnt;
    int mi[len+1],res[maxn];
    int q[3][maxn];//q[0] -> 哪一位 q[1] -> na q[2] -> nb
    struct Trie{
    	int tot=1;
    	int num[maxn];
    	int ch[maxn][2];
    	//{{{insert
    	void insert (int s)
    	{
    		int now=1;
    		for (int i=len;i>=0;--i){
    			bool to=s&mi[i];
    			if (!ch[now][to]) ch[now][to]=++tot;
    			now=ch[now][to];
    			++num[now];
    		}
    	}
    	//}}}
    }A,B;
    //{{{dfs
    void dfs(int x,int y,int S,int k)
    {
    	if(x) --A.num[x],--B.num[y];
    	if(k<0) {	res[++cnt]=S;return;}
    	while(A.num[A.ch[x][0]]&&B.num[B.ch[y][0]])  dfs(A.ch[x][0],B.ch[y][0],S,k-1);
    	while(A.num[A.ch[x][1]]&&B.num[B.ch[y][1]])  dfs(A.ch[x][1],B.ch[y][1],S,k-1);
    	while(A.num[A.ch[x][0]]&&B.num[B.ch[y][1]])  dfs(A.ch[x][0],B.ch[y][1],S|mi[k],k-1);
    	while(A.num[A.ch[x][1]]&&B.num[B.ch[y][0]])  dfs(A.ch[x][1],B.ch[y][0],S|mi[k],k-1);
    }
    //}}}
    int main()
    {
    	mi[0]=1;
    	for (int i=1;i<=len;++i)	mi[i]=mi[i-1]<<1;
    	cin>>n;
    	for (int i=1;i<=n;++i)	cin>>a,A.insert(a);
    	for (int i=1;i<=n;++i)	cin>>b,B.insert(b);
    	dfs(1,1,0,30);
    	sort(res+1,res+n+1);
    	for (int i=1;i<=n;++i)	printf("%d ",res[i]);
    	return 0;
    }
    
    
    

    如有哪里讲得不是很明白或是有错误,欢迎指正
    如您喜欢的话不妨点个赞收藏一下吧

  • 相关阅读:
    CompletableFuture java 8新增加异步处理
    Java并发编程:CountDownLatch、CyclicBarrier和 Semaphore , Condition
    怎么让一个不定宽高的div垂直水平居中?
    数组对象方法排序
    Webpack ERROR in Path must be a string. Received undefined
    es6 babel转码器安装配置及常见命令
    使用淘宝镜像cnpm安装Vue.js
    JS中的call()和apply()方法
    placeholder颜色更改
    typeof与js数据类型
  • 原文地址:https://www.cnblogs.com/Morning-Glory/p/11528014.html
Copyright © 2011-2022 走看看