CF1416C XOR Inverse

题目链接

CF1416C XOR Inverse

题目描述

You are given an array a consisting of n non-negative integers. You have to choose a non-negative integer x and form a new array b of size n according to the following rule: for all i from 1 to n, bi=aix( denotes the operation bitwise XOR).

An inversion in the b array is a pair of integers i and j such that 1i<jn and bi>bj.
You should choose x in such a way that the number of inversions in b is minimized. If there are several options for x - output the smallest one.

输入格式

First line contains a single integer n(1n3105) the number of elements in a.
Second line contains n space-separated integers a1,a2,,an(0ai109), where ai is the i th element of a.

输出格式

Output two integers: the minimum possible number of inversions in b, and the minimum possible value of x, which achieves those number of inversions.

题目翻译

给定长度为 n(1n3×105) 的数列 {an}(0an109) ,请求出最小的整数 x 使 {anx} 的 逆序对数最少,其中 是异或

输入格式

第一行 n ,第二行 {an}

输出格式

两个数,逆序对数和 x

解题思路

01trie

建立一棵下标01trie,即每插入一个数,在每个节点记录该数的下标,可知每个节点中的下标都是递增的,对于一棵子树来说,其右子树的值都要大于左子树,现在要求的即为右子树中下标小于左子树的对数,进而求出该子树的逆序对数量,当 x 对应该位的值为 1 时,即左右子树交换位置,逆序对的个数为总的对数减去原逆序对的数量,x 某一位为 1 当前仅当该位取 1 时的逆序对数量小于取 0 时的逆序对数量

  • 时间复杂度:O(30n)

代码

// Problem: CF1416C XOR Inverse // Contest: Luogu // URL: https://www.luogu.com.cn/problem/CF1416C // Memory Limit: 500 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=9e6+5; vector<int> pos[N]; int trie[N][2],idx,n; LL f[30][2]; void insert(int x,int id) { int p=0; for(int i=29;~i;i--) { int t=x>>i&1; if(trie[p][t]==0)trie[p][t]=++idx; p=trie[p][t]; pos[p].pb(id); } } void dfs(int u,int p) { int l=trie[u][0],r=trie[u][1]; if(l)dfs(l,p-1); if(r)dfs(r,p-1); if(!l&&!r)return ; LL res=0; int num=0; for(int i:pos[l]) { while(num<pos[r].size()&&pos[r][num]<i)num++; res+=num; } f[p][0]+=res; f[p][1]+=pos[l].size()*pos[r].size()-res; } int main() { cin>>n; for(int i=1;i<=n;i++) { int x; cin>>x; insert(x,i); } dfs(0,29); LL inv=0; int x=0; for(int i=29;~i;i--) { inv+=min(f[i][0],f[i][1]); if(f[i][1]<f[i][0])x+=1<<i; } cout<<inv<<' '<<x; return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/15979960.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示