CodeForces - 1417E XOR Inverse(字典树求逆序对+分治)
题目链接:点击查看
题目大意:给出一个长度为 n 的数列 a,现在要求选出一个 x,将 a 中的每个元素都异或之后得到一个新的数列 b,要求数列 b 的逆序对最小,问最小的逆序对是多少,x 该如何选择
题目分析:才知道字典树上分治也可以求逆序对,时间复杂度是 nlogn 的,做法如下:
- 将每个数都插入到字典树中,记录一下其下标
- 对于某个节点来说,其左子树中的点一定小于其右子树中的点
- 所以遍历一遍左子树中的点,双指针找一下右子树中有多少个点的下标大于当前枚举的点,累加起来就是逆序对的个数了
因为每一层最多有 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(字典树求逆序对+分治)相关推荐
- 线段树求逆序对(hdu1394Minimum Inversion Number)
说实话,线段树求逆序对我理解了半天诶,不知是否有人像我一样. 对于每个数来说,只有和已经出现过的.比它大的数才能形成逆序对,那么在给定的数列中,每给一个数就向前找比它大的数. 样例:10 1 3 6 ...
- HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911 解题报告: 给出一个长度为n的序列,然后给出一个k,要你求最多做k次相邻的数字交换后,逆序数最少 ...
- 用不同的姿势求逆序对(复习篇)
用不同的姿势求逆序对(复习篇) 文章目录 用不同的姿势求逆序对(复习篇) 前言 讲解 归并排序 树状数组 线段树 题目 思路 代码 归并排序求逆序对 树状数组求逆序对 线段树求逆序对 历届试题 小朋友 ...
- szu 寒训第二天 树状数组 二维树状数组详解,以及树状数组扩展应用【求逆序对,以及动态第k小数】
树状数组(Binary Index Tree) 树状数组可以解决可以转化为前缀和问题的问题 这是一类用以解决动态前缀和的问题 (有点像线段树简版) 1.对于 a1 + a2 + a3 + - + an ...
- Tido 习题-二叉树-树状数组求逆序对
这里给大家提供一个全新的求逆序对的方法 是通过树状数组来实现的 题目描述 样例输入 Copy 5 2 3 1 5 4 样例输出 Copy 3 提示 #include<iostre ...
- codevs1688 求逆序对(权值线段树)
1688 求逆序对 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 给定一个序列a1,a2,-,an,如 ...
- 树状数组求逆序对_区间和的个数(树状数组)
327. 区间和的个数 给定一个整数数组 nums,返回区间和在 [lower, upper] 之间的个数,包含 lower 和 upper. 区间和 S(i, j) 表示在 nums 中,位置从 i ...
- 树状数组的相关知识 及 求逆序对的运用
文章目录 树状数组概念 前缀和和区间和 树状数组原理 区间和--单点更新 前缀和--区间查询 完整代码 离散化 sort函数 unique函数去重 erase函数仅保留不重复元素 通过树状数组求逆序对 ...
- 树状数组(求逆序对)
一.树状数组是什么 树状数组,又称二进制索引树,英文名Binary Indexed Tree 之前遇到一个求逆序对的题,看了很多题解都只说了这个树状数组,关于怎么实现的全都避而不谈,我研究了一下午,总 ...
最新文章
- python可以处理任何字符编码文本_python数据类型、字符编码、文件处理
- STM32F4 HAL库开发 -- 独立看门狗(IWDG)
- Android无线测试之—UiAutomator UiDevice API介绍六
- 帆软报表重要Activator之DesignerInitActivator之四WestRegionContainerPane 设计器的左边部分文件列表以及数据集的部分
- 身为华人,我再一次不淡定了,中文输入项目启动
- Windows数据类型探幽
- 机房服务器维修合同,机房维护合同模板.doc
- 八:Webpack的加载器
- pkuseg 和 jieba 分词对比测试,结果出乎意料...
- App保持登录状态的常用方法
- [Qt] 基于Tcp协议的聊天室实现(Chat Room 局域网通信)
- 淘宝美工图片处理规范
- 实现Comparable接口和Comparator接口
- Window10总是自动打开网络代理的解决方案法
- 网络带宽和下载速度的换算
- 『WPF』TextBox元素过滤键盘输入
- react分页组件实现:DiReactPagination
- linux ethtool 命令详解
- 开源社邀请您参加2022 第四届天津前端开发者大会
- 【面试题】【C语言】5位运动员参加跳水比赛,有人让他们预测比赛结果