zoukankan      html  css  js  c++  java
  • three arrays HDU

    three arrays

    [Time Limit: 2500 ms quad Memory Limit: 262144 kB ]

    题意

    给出 (a)(b) 数组,定义数组 (c[i] = a[i] XOR b[i]),现在可以任意调整 (a)(b) 的顺序,使得最后的 (c) 字典序最小。

    思路

    对于 (a) 数组和 (b) 数组分别建立字典树,然后从大到小在字典树上贪心构造尽量小的 (c)
    对于某一位,如果两颗树上同时有 (00) 或者 (11),那么就选择往这样的边 (dfs),否则的话往 (01) 或者 (10)(dfs),并加上这一位的异或值。
    因为 (01)(10) 不可能同时出现,因为如果同时出现了,肯定优先去 (00) 或者 (11)。那么就是 (00)(11) 的情况,可能出现往 (00) 的答案是 (4),往 (11) 的答案是 (3),那么无法让小的先出来,所以可以任一选一个走,把另一个留到后面走,然后对于所有求出来的 (c)(sort) 一遍。

    /*************************************************************** 
        > File Name    : a.cpp
        > Author       : Jiaaaaaaaqi
        > Created Time : Fri 06 Sep 2019 09:17:26 PM CST
     ***************************************************************/
    
    #include <map>
    #include <set>
    #include <list>
    #include <ctime>
    #include <cmath>
    #include <stack>
    #include <queue>
    #include <cfloat>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <bitset>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define  lowbit(x)  x & (-x)
    #define  mes(a, b)  memset(a, b, sizeof a)
    #define  fi         first
    #define  se         second
    #define  pb         push_back
    #define  pii        pair<int, int>
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const int    maxn = 1e5 + 10;
    const int    maxm = 1e5 + 10;
    const ll     mod  = 1e9 + 7;
    const ll     INF  = 1e18 + 100;
    const int    inf  = 0x3f3f3f3f;
    const double pi   = acos(-1.0);
    const double eps  = 1e-8;
    using namespace std;
    
    int n, m;
    int cas, tol, T;
    
    int tot[2];
    int a[maxn], b[maxn], c[maxn];
    int node[2][maxn*30][2], cnt[2][maxn*30];
    
    void insert(int x, int id) {
    	int rt = 0;
    	for(int i=30; i>=1; i--) {
    		int f = (x&(1<<(i-1))) ? 1 : 0;
    		if(node[id][rt][f] == 0) {
    			tot[id]++;
    			mes(node[id][tot[id]], 0);
    			cnt[id][tot[id]] = 0;
    			node[id][rt][f] = tot[id];
    		}
    		rt = node[id][rt][f];
    		cnt[id][rt]++;
    	}
    }
    
    int dfs(int rt1, int rt2, int p) {
    	// printf("rt1=%d rt2=%d
    ", rt1, rt2);
    	if(p == 0)	return 0;
    	bool ok00 = (node[0][rt1][0] && cnt[0][node[0][rt1][0]]);
    	bool ok01 = (node[0][rt1][1] && cnt[0][node[0][rt1][1]]);
    	bool ok10 = (node[1][rt2][0] && cnt[1][node[1][rt2][0]]);
    	bool ok11 = (node[1][rt2][1] && cnt[1][node[1][rt2][1]]);
    	if(ok00 && ok10) {
    		cnt[0][node[0][rt1][0]]--, cnt[1][node[1][rt2][0]]--;
    		return dfs(node[0][rt1][0], node[1][rt2][0], p-1);
    	} else if(ok01 && ok11) {
    		cnt[0][node[0][rt1][1]]--, cnt[1][node[1][rt2][1]]--;
    		return dfs(node[0][rt1][1], node[1][rt2][1], p-1);
    	} else if(ok00 && ok11) {
    		cnt[0][node[0][rt1][0]]--, cnt[1][node[1][rt2][1]]--;
    		return dfs(node[0][rt1][0], node[1][rt2][1], p-1) + (1<<(p-1));
    	} else {
    		cnt[0][node[0][rt1][1]]--, cnt[1][node[1][rt2][0]]--;
    		return dfs(node[0][rt1][1], node[1][rt2][0], p-1) + (1<<(p-1));
    	}
    }
    
    int main() {
    	// freopen("in", "r", stdin);
    	scanf("%d", &T);
    	while(T--) {
    		cnt[0][0] = cnt[1][0] = tot[0] = tot[1] = 0;
    		mes(node[0][0], 0), mes(node[1][0], 0);
    		scanf("%d", &n);
    		for(int i=1; i<=n; i++)	scanf("%d", &a[i]), insert(a[i], 0);
    		for(int i=1; i<=n; i++)	scanf("%d", &b[i]), insert(b[i], 1);
    		for(int i=1; i<=n; i++)	c[i] = dfs(0, 0, 30);
    		sort(c+1, c+1+n);
    		for(int i=1; i<=n; i++)	printf("%d%c", c[i], i==n ? '
    ' : ' ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    方法的重载;数组 (Java Day05)
    switch语句;for/while循环;死循环;跳转语句;嵌套循环;方法及方法的调用(Java Day04)
    运算符;键盘录入;分支结构(Java Day03)
    基础概念学习;常量;变量;编码表;数据类型转换(Java Day02)
    Java语言基本概述;入门案例学习;环境变量的配置;Eclipse安装(Java Day01)
    JVM内存模型
    java多线程对CountDownLatch的使用
    System.nanoTime()的使用
    this用法
    idea取消重复代码提醒的功能
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/11478595.html
Copyright © 2011-2022 走看看