题目链接:点击查看

题目大意:给出一个长度为 n 的数列 a,现在要求选出一个 x,将 a 中的每个元素都异或之后得到一个新的数列 b,要求数列 b 的逆序对最小,问最小的逆序对是多少,x 该如何选择

题目分析:才知道字典树上分治也可以求逆序对,时间复杂度是 nlogn 的,做法如下:

  1. 将每个数都插入到字典树中,记录一下其下标
  2. 对于某个节点来说,其左子树中的点一定小于其右子树中的点
  3. 所以遍历一遍左子树中的点,双指针找一下右子树中有多少个点的下标大于当前枚举的点,累加起来就是逆序对的个数了

因为每一层最多有 n 个数,一共有 logn 层,所以遍历的次数约等于 nlogn 次

现在考虑该如何计算 x,假设 x 中的某一位为 0,那么在字典树上将不产生影响,如果其中的某一位为 1 ,将对其对应层数的所有节点的左右子树互换,注意这个过程中,只会影响到当前层数的逆序对,而不会影响到其他的层数的答案,换句话说,在这个题目中,x 中的每一位相互独立

再考虑如果 x 的某一位是 1 的话会造成什么影响,设原本的逆序对为 ans1,顺序对为 ans2,如果将该层的左右子树互换的话,那么 ans1 和 ans2 的值也会相应的被交换,所以我们可以对于每一层统计一下 dp[ deep ][ 0 ] 和 dp[ deep ][ 1 ] 分别表示当前层数中逆序对和顺序对的个数,如果某一层的逆序对更少,显然当前位填 0 更优,否则填 1 更优

代码:

#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","inline","-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=3e5+100;vector<int>node[N*40];int trie[N*40][2],cnt;LL dp[40][2];int newnode()
{cnt++;trie[cnt][0]=trie[cnt][1]=0;node[cnt].clear();return cnt;
}void insert(int x,int id)
{int pos=0;for(int i=30;i>=0;i--){int to=(x>>i)&1;if(!trie[pos][to])trie[pos][to]=newnode();pos=trie[pos][to];node[pos].push_back(id);}
}void dfs(int pos,int deep)
{if(deep==-1)return;int lson=trie[pos][0],rson=trie[pos][1];LL res=0,r=0;int lsz=node[lson].size(),rsz=node[rson].size();for(int i=0;i<lsz;i++){while(r<rsz&&node[lson][i]>node[rson][r])r++;res+=r;}dp[deep][0]+=res;dp[deep][1]+=1LL*lsz*rsz-res;if(lson)dfs(lson,deep-1);if(rson)dfs(rson,deep-1);
}void init()
{cnt=-1;newnode();
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);init();int n;scanf("%d",&n);for(int i=1;i<=n;i++){int num;scanf("%d",&num);insert(num,i);}dfs(0,30);LL ans=0,x=0;for(int i=0;i<=30;i++){if(dp[i][0]<=dp[i][1])ans+=dp[i][0];else{ans+=dp[i][1];x|=(1<<i);}}printf("%lld %lld\n",ans,x);return 0;
}

CodeForces - 1417E XOR Inverse(字典树求逆序对+分治)相关推荐

  1. 线段树求逆序对(hdu1394Minimum Inversion Number)

    说实话,线段树求逆序对我理解了半天诶,不知是否有人像我一样. 对于每个数来说,只有和已经出现过的.比它大的数才能形成逆序对,那么在给定的数列中,每给一个数就向前找比它大的数. 样例:10 1 3 6 ...

  2. HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911 解题报告: 给出一个长度为n的序列,然后给出一个k,要你求最多做k次相邻的数字交换后,逆序数最少 ...

  3. 用不同的姿势求逆序对(复习篇)

    用不同的姿势求逆序对(复习篇) 文章目录 用不同的姿势求逆序对(复习篇) 前言 讲解 归并排序 树状数组 线段树 题目 思路 代码 归并排序求逆序对 树状数组求逆序对 线段树求逆序对 历届试题 小朋友 ...

  4. szu 寒训第二天 树状数组 二维树状数组详解,以及树状数组扩展应用【求逆序对,以及动态第k小数】

    树状数组(Binary Index Tree) 树状数组可以解决可以转化为前缀和问题的问题 这是一类用以解决动态前缀和的问题 (有点像线段树简版) 1.对于 a1 + a2 + a3 + - + an ...

  5. Tido 习题-二叉树-树状数组求逆序对

    这里给大家提供一个全新的求逆序对的方法 是通过树状数组来实现的 题目描述   样例输入 Copy 5 2 3 1 5 4 样例输出 Copy 3 提示       #include<iostre ...

  6. codevs1688 求逆序对(权值线段树)

    1688 求逆序对  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果 题目描述 Description 给定一个序列a1,a2,-,an,如 ...

  7. 树状数组求逆序对_区间和的个数(树状数组)

    327. 区间和的个数 给定一个整数数组 nums,返回区间和在 [lower, upper] 之间的个数,包含 lower 和 upper. 区间和 S(i, j) 表示在 nums 中,位置从 i ...

  8. 树状数组的相关知识 及 求逆序对的运用

    文章目录 树状数组概念 前缀和和区间和 树状数组原理 区间和--单点更新 前缀和--区间查询 完整代码 离散化 sort函数 unique函数去重 erase函数仅保留不重复元素 通过树状数组求逆序对 ...

  9. 树状数组(求逆序对)

    一.树状数组是什么 树状数组,又称二进制索引树,英文名Binary Indexed Tree 之前遇到一个求逆序对的题,看了很多题解都只说了这个树状数组,关于怎么实现的全都避而不谈,我研究了一下午,总 ...

最新文章

  1. python可以处理任何字符编码文本_python数据类型、字符编码、文件处理
  2. STM32F4 HAL库开发 -- 独立看门狗(IWDG)
  3. Android无线测试之—UiAutomator UiDevice API介绍六
  4. 帆软报表重要Activator之DesignerInitActivator之四WestRegionContainerPane 设计器的左边部分文件列表以及数据集的部分
  5. 身为华人,我再一次不淡定了,中文输入项目启动
  6. Windows数据类型探幽
  7. 机房服务器维修合同,机房维护合同模板.doc
  8. 八:Webpack的加载器
  9. pkuseg 和 jieba 分词对比测试,结果出乎意料...
  10. App保持登录状态的常用方法
  11. [Qt] 基于Tcp协议的聊天室实现(Chat Room 局域网通信)
  12. 淘宝美工图片处理规范
  13. 实现Comparable接口和Comparator接口
  14. Window10总是自动打开网络代理的解决方案法
  15. 网络带宽和下载速度的换算
  16. 『WPF』TextBox元素过滤键盘输入
  17. react分页组件实现:DiReactPagination
  18. linux ethtool 命令详解
  19. 开源社邀请您参加2022 第四届天津前端开发者大会
  20. 【面试题】【C语言】5位运动员参加跳水比赛,有人让他们预测比赛结果

热门文章

  1. linux 字符串转数字排序,linux中sort命令排序功能实现方法
  2. 自我引用(Self reference)
  3. MyBatis 缓存详解-开启二级缓存的方法
  4. RocketMQ核心架构和概
  5. (常用API)正则表达式匹配练习
  6. 资源权限操作-添加资源权限
  7. 文件上传之传统方式上传代码回顾
  8. 初始化方法-在类的外部给对象增加属性的隐患
  9. 全局变量-全局变量定义的位置及代码结构
  10. Eureka常用配置详解