[杭电多校] 2019第五场B 01Trie+贪心

题意:给定两个等长数组a,b,你可以随意排列他们,使得数组c字典序最小,其中c[i]=a[i] xor b[i]。

思路:题解的做法貌似很复杂,但在直接建两棵01Trie,在01Trie上贪心的做法也能通过。

public class Main {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader sc = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        long s=System.currentTimeMillis();
        Task solver = new Task();
        solver.solve(1, sc, out);
        long e=System.currentTimeMillis();
    //    System.out.println(e-s);
        out.close();
    }

    static class Task {
    	public static final int Max=(int) (1e5+10);
    	public ZeroOneTrie t1;
    	public ZeroOneTrie t2;
    	
    	public ArrayList<Integer> get(int n){
    		ArrayList<Integer> buf=new ArrayList<Integer>();
    		
    		
    		while(n-->0) {
    			int res=0;
    			int index1=0;
    	    	int index2=0;
    			for(int i=30;i>=0;i--) {
    				if(t1.cnt[t1.next[index1][0]]>0&&t2.cnt[t2.next[index2][0]]>0) {
    					t1.cnt[t1.next[index1][0]]--;
    					t2.cnt[t2.next[index2][0]]--;
    					index1=t1.next[index1][0];
    					index2=t2.next[index2][0];
    				}
    				else
    					if(t1.cnt[t1.next[index1][1]]>0&&t2.cnt[t2.next[index2][1]]>0) {
    						t1.cnt[t1.next[index1][1]]--;
        					t2.cnt[t2.next[index2][1]]--;
        					index1=t1.next[index1][1];
        					index2=t2.next[index2][1];
    					}
    				else
    					if(t1.cnt[t1.next[index1][0]]>0&&t2.cnt[t2.next[index2][1]]>0) {
    						res|=1<<i;
    						t1.cnt[t1.next[index1][0]]--;
        					t2.cnt[t2.next[index2][1]]--;
        					index1=t1.next[index1][0];
        					index2=t2.next[index2][1];
    					}
    				else {
    					res|=1<<i;
						t1.cnt[t1.next[index1][1]]--;
    					t2.cnt[t2.next[index2][0]]--;
    					index1=t1.next[index1][1];
    					index2=t2.next[index2][0];
    				}
    			}
    			buf.add(res);
    		}
    		
    		return buf;
    	}
    	
    	
        public void solve(int testNumber, InputReader sc, PrintWriter out) throws IOException {
        	int T=sc.nextInt();
        	int[] a=new int[Max];
        	int[] b=new int[Max];
        	t1=new ZeroOneTrie(Max);
        	t2=new ZeroOneTrie(Max);
        	long s=System.currentTimeMillis();
        	
        	while(T-->0) {
        		t1.init();
        		t2.init();
        		int n=sc.nextInt();
        		for(int i=1;i<=n;i++) {
        			a[i]=sc.nextInt();
        			t1.insert(a[i]);
        		}
        		for(int i=1;i<=n;i++) {
        			b[i]=sc.nextInt();
        			t2.insert(b[i]);
        		}
        		//long e=System.currentTimeMillis();
        	//	System.out.println((e-s)+"ms");
        		ArrayList<Integer> res=get(n);
        		Collections.sort(res);
        	    out.print(res.get(0));
        	    for(int i=1;i<res.size();i++)
        	    	out.print(" "+res.get(i));
        	    out.println();
        	   // e=System.currentTimeMillis();
        		//System.out.println((e-s)+"ms");
        	}
        /*	long e=System.currentTimeMillis();
    		System.out.println((e-s)+"ms");*/
        }
    }
    
    static class ZeroOneTrie{
		public int tot;
		public int[][] next;
		public int n;
	//	public int[] val;
		public int[] cnt;
		
		public ZeroOneTrie(int n) {
			this.n=n;
			this.tot=0;
			this.next=new int[(n+10)<<5][2];
		//	this.val=new int[(n+10)<<5];
			this.cnt=new int[(n+10)<<5];
		}
		
		public void init() {
			this.tot=0;
			cnt[next[0][0]]=cnt[next[0][1]]=0;
			next[0][0]=next[0][1]=0;
		}
		
		public void insert(int x) {
			 int index=0;
		       for(int i=30;i>=0;i--){
		            int to=(x>>i)&1;
		            if(next[index][to]==0){
		                next[index][to]=++tot;
		                cnt[next[tot][0]]=cnt[next[tot][1]]=0;
		                next[tot][0]=next[tot][1]=0;    //把将指向的下一个节点初始化
		              //  val[tot]=0;
		                cnt[tot]=0;
		            }
		            index=next[index][to];
		            cnt[index]++;
		       }
		   // val[index]=x;
		}
		
		public int ask(int x,int k) {      //从当前插入的所有数字中返回与x异或值第k小的一个数
			int index=0;
			int res=0;
			
			for(int i=30;i>=0;i--) {
				int to=(x>>i)&1;
				if(k>cnt[next[index][to]]) {
					k-=cnt[next[index][to]];
					res|=1<<i;
					index=next[index][to^1];
				}
				else
					index=next[index][to];
			}
			
			return res;
		}

		
	/*	public int ask(int x) {      //从当前插入的所有数字中返回与x异或值最大的一个数
			int index=0;
			
			for(int i=30;i>=0;i--) {
				int to=(x>>i)&1;
				if(next[index][to^1]!=0&&cnt[next[index][to^1]]>0)      
					index=next[index][to^1];
				else
					index=next[index][to];
			}
			
			return val[index];
		}*/
		
		public void del(int x) {
			int index=0;
			
			for(int i=30;i>=0;i--) {
				int to=(x>>i)&1;
				index=next[index][to];
				cnt[index]--;
			}
		}
	}

    static class InputReader{
        StreamTokenizer tokenizer;
        public InputReader(InputStream stream){
            tokenizer=new StreamTokenizer(new BufferedReader(new InputStreamReader(stream)));
            tokenizer.ordinaryChars(33,126);
            tokenizer.wordChars(33,126);
        }
        public String next() throws IOException {
            tokenizer.nextToken();
            return tokenizer.sval;
        }
        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }
        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }
        public boolean hasNext() throws IOException {
            int res=tokenizer.nextToken();
            tokenizer.pushBack();
            return res!=tokenizer.TT_EOF;
        }
        
        public double nextDouble() throws NumberFormatException, IOException {
        	return Double.parseDouble(next());
        }
        
        public BigInteger nextBigInteger() throws IOException {
        	return new BigInteger(next());
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值