题目传送门

  这是一条通往vjudge的高速公路

  这是一条通往Codeforces的高速公路

题目大意

  给定一个$n$阶完全图,每个点有一个权值$a_{i}$,边$(i, j)$的权值是$(a_{i}\  xor\  a_{j})$。一个生成树的权值是各边的权值和。问最小生成树的权值。  

  设值域为$[0, 2^{k})$。

  当$k = 1$的时候,显然将点权为0的点之间互相连边,点权为1的点之间互相连边,中间随便连一条。

  当$k = x\ (x > 1)$的时候,将这些点按照二进制的第$k$位分成两个集合。因为这两集合中间的点互相连边,边权的第$k$位会被消掉,于是变成了$k = x - 1$的子问题。

  假如得到了它们的最优解,那么我只需要在两个连通块之间添加一条边权最小的边就行了。

  考虑怎么找这样一条边。

  我可以把其中一个集合中数插入Trie树,然后拿另一集合中的点的点权在Trie树中查最小异或和。

Code

 /**
* Codeforces
* Problem#888G
* Accepted
* Time: 327ms
* Memory: 49772k
*/
#include <bits/stdc++.h>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean; #define ll long long typedef class TrieNode {
public:
TrieNode* ch[]; TrieNode():ch({NULL, NULL}) { }
}TireNode; TrieNode pool[];
TrieNode* top = pool; TrieNode* newnode() {
top->ch[] = top->ch[] = NULL;
return top++;
} typedef class Trie {
public:
TrieNode* rt; Trie() {
top = pool;
rt = newnode();
} void insert(int x, int dep) {
int temp = << dep, d;
TrieNode *p = rt;
while (temp) {
d = (temp & x) ? () : ();
if (!p->ch[d])
p->ch[d] = newnode();
p = p->ch[d], temp = temp >> ;
}
} int query(int x, int dep) {
int temp = << dep, rt = , d;
TrieNode *p = this->rt;
while (temp) {
d = (temp & x) ? () : ();
if (p->ch[d])
p = p->ch[d];
else
p = p->ch[d ^ ], rt |= temp;
temp = temp >> ;
}
return rt;
}
}Trie; int n;
int *ar;
Trie t; inline void init() {
scanf("%d", &n);
ar = new int[(n + )];
for (int i = ; i <= n; i++)
scanf("%d", ar + i);
} ll dividing(int dep, int l, int r) {
if (!dep) return ar[l] ^ ar[r];
int tl = l, tr = r, mid, temp = << dep, mincost = << ;
while (tl <= tr) {
mid = (tl + tr) >> ;
if (ar[mid] & temp)
tr = mid - ;
else
tl = mid + ;
}
if (tr == l - || tr == r)
return dividing(dep - , l, r);
t = Trie();
for (int i = l; i <= tr; i++)
t.insert(ar[i], dep);
for (int i = tr + ; i <= r; i++)
mincost = min(mincost, t.query(ar[i], dep));
return mincost + dividing(dep - , l, tr) + dividing(dep - , tr + , r);
} inline void solve() {
sort(ar + , ar + n + );
printf(Auto"\n", dividing(, , n));
} int main() {
init();
solve();
return ;
}

Codeforces 888G Xor-MST - 分治 - 贪心 - Trie的更多相关文章

  1. Codeforces 1111C Creative Snap分治+贪心

    Creative Snap C. Creative Snap time limit per test 1 second memory limit per test 256 megabytes inpu ...

  2. 51nod1295 XOR key(可持久化trie)

    1295 XOR key题目来源: HackerRank基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160 难度:6级算法题 给出一个长度为N的正整数数组A,再给出Q个查询,每个查 ...

  3. codeforces Gym 100338E Numbers (贪心,实现)

    题目:http://codeforces.com/gym/100338/attachments 贪心,每次枚举10的i次幂,除k后取余数r在用k-r补在10的幂上作为候选答案. #include< ...

  4. AcWing:105. 七夕祭(前缀和 + 中位数 + 分治 + 贪心)

    七夕节因牛郎织女的传说而被扣上了「情人节」的帽子. 于是TYVJ今年举办了一次线下七夕祭. Vani同学今年成功邀请到了cl同学陪他来共度七夕,于是他们决定去TYVJ七夕祭游玩. TYVJ七夕祭和11 ...

  5. [多校联考2019(Round 4 T1)][51nod 1295]Xor key(可持久化trie)

    [51nod 1295]Xor key(可持久化trie) 题面 给出一个长度为n的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X (L <= R).求A[L] 至 A[R] ...

  6. [Codeforces 1214A]Optimal Currency Exchange(贪心)

    [Codeforces 1214A]Optimal Currency Exchange(贪心) 题面 题面较长,略 分析 这个A题稍微有点思维难度,比赛的时候被孙了一下 贪心的思路是,我们换面值越小的 ...

  7. Codeforces.888G.Xor-MST(Borůvka算法求MST 贪心 Trie)

    题目链接 \(Description\) 有一张\(n\)个点的完全图,每个点的权值为\(a_i\),两个点之间的边权为\(a_i\ xor\ a_j\).求该图的最小生成树. \(n\leq2*10 ...

  8. Codeforces 888G(分治+trie)

    按位贪心,以当前考虑位是0还是1将数分成两部分,则MST中这两部分之间只会存在一条边,因为一旦有两条或以上的边,考虑两条边在原图中所成的环,显然这两条边有一条是环上的权值最大边,不会出现在MST中.则 ...

  9. Codeforces 437D The Child and Zoo - 树分治 - 贪心 - 并查集 - 最大生成树

    Of course our child likes walking in a zoo. The zoo has n areas, that are numbered from 1 to n. The ...

随机推荐

  1. ubuntu下ldd,查看程序动态库信息

    ldd  list, dynamic, dependencies linux-vdso.so. => (0x00007ffe9d9b6000) libstdc++.so. => /usr/ ...

  2. Cocos Creator 对象池cc.NodePool的使用

    对象池cc.NodePool把层级管理器中的节点拖进资源管理器中就创建了预制体:let和var 一样,是声明变量的关键词, 同一个变量名时,var 即使在{}内也作用全局,let有范围:(1)将需要数 ...

  3. git add -A -u . 的区别

    git add -u:将文件的修改.文件的删除,添加到暂存区. git add .:将文件的修改,文件的新建,添加到暂存区. git add -A:将文件的修改,文件的删除,文件的新建,添加到暂存区.

  4. HDU 2604 Queuing(递推+矩阵)

    Queuing [题目链接]Queuing [题目类型]递推+矩阵 &题解: 这题想是早就想出来了,就坑在初始化那块,只把要用的初始化了没有把其他的赋值为0,调了3,4个小时 = = 本题是可 ...

  5. Linux shell脚本 批量创建多个用户

    Linux shell脚本 批量创建多个用户 #!/bin/bash groupadd charlesgroup for username in charles1 charles2 charles3 ...

  6. linux设置时间显示格式和系统版本

    [修改显示日期格式] vim /etc/bashrc alias ll='ls -l --time-style="+%Y-%m-%d %H:%M:%S"' alias date=' ...

  7. arc 092D Two Sequences

    题意: 给出两个长度N相同的整数序列A和B,有N^2种方式从A中选择一个数Ai,从B中选择一个数Bj,让两个数相加,求这N^2个数的XOR,即异或. 思路: 暴力的求显然是会超时的,因为是异或,就考虑 ...

  8. 20155228 实验二 Java面向对象程序设计

    20155228 实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原 ...

  9. Spark学习之路 (二十七)图简介

    一.图 1.1 基本概念 图是由顶点集合(vertex)及顶点间的关系集合(边edge)组成的一种数据结构. 这里的图并非指代数中的图.图可以对事物以及事物之间的关系建模,图可以用来表示自然发生的连接 ...

  10. for-each 循环原理

    for-each 循环原理1,for-each 是在java5 之后出现的.for是java 上的一个关键字,在jdk 找不到任何for的底层实现的.是因为for的底层实现被封装到了编译器中.所以通过 ...