[CF1416C] XOR Inverse - Trie

Description

给定长度为 \(n\) \((1\le n\le3\times 10^5)\) 的数列 \(\{a_n\}\) \((0\le a_n\le 10^9)\),请求出最小的整数 \(x\) 使 \(\{a_n\oplus x\}\) 的逆序对数最少。

Solution

对于任意两个数,如果他们不同,那么一定存在一个最高的位 i,使得 i+1,i+2,...,M-1 位都相同,但 i 位不同

对于每两个数,我们都找到这样的最高位 k,并把第 k 位是 0 的那个数记作前项,是 1 的那个数记作后项,构成有序对 (i,j)

如果 \(i>j\) 的个数多于 \(i<j\) 的个数,那么 x 的这一位填 1,否则填 0

用 trie 树来统计即可

#include <bits/stdc++.h>
using namespace std;

#define int long long 
const int N = 1e7+5;

int n;
int a[N];
int siz[N];
int ch[N][2];
int cnt[33][2];
int ind,x,ans;

signed main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        int p=0;
        for(int j=30;j>=0;j--)
        {
            int c=(a[i]>>j)&1;
            cnt[j][c]+=siz[ch[p][c^1]];
            if(ch[p][c]==0) ch[p][c]=++ind;
            siz[ch[p][c]]++;
            p=ch[p][c];
        }
    }
    for(int i=0;i<=30;i++)
    {
        ans+=min(cnt[i][0],cnt[i][1]);
        if(cnt[i][1]<cnt[i][0]) x+=1<<i;
    }
    cout<<ans<<" "<<x<<endl;
}

相关文章:

  • 2021-09-28
  • 2021-12-28
  • 2021-10-21
  • 2022-12-23
  • 2022-12-23
  • 2021-09-08
  • 2022-02-27
  • 2021-12-27
猜你喜欢
  • 2022-01-16
  • 2022-12-23
  • 2022-01-19
  • 2021-11-04
  • 2021-08-30
  • 2022-01-02
  • 2022-01-10
相关资源
相似解决方案