Specific 2300+:. G Xor-MST (Minimum Spanning Tree or Trie tree exclusive)

Original title: http://codeforces.com/contest/888/problem/G

Meaning of the questions:

2e5 given point, the right side of the right or outliers, minimum spanning tree.

Resolution:

The so-called Boruvka's algorithm , that is, only if the two sets, so I'm sure the right choice for a minimum of side edge connects two sets.

Here are just apply a similar idea.

For the value of each point in binary build the Trie.
Here Insert Picture Description
In the second layer, for example, the left point is ( 000 , 010 , 011 000,010,011 ), the right ( 101 , 110 , 1111 101,110,1111 ). If the point is connected to the left point to the right, then the right side will contain ( 100 100 ) In this section, the value is very large, so you can draw emotional: a collection of left and right set of connected only by an edge.

And all connection sets down to do just a recursive subset can be.


This edge derived: through all points to the left, to the right to find a minimum XOR up, and then to take min.

XOR together to find the smallest is also very easy, direct from top to bottom can be greedy.

note: an array of open 4e6 will TLE

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=8e6+9;
int a[maxn],l[maxn],r[maxn],son[maxn][2],num;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
  return *p1++;
}

inline void read(int &x){
  char c=nc(),b=1;
  if(c==EOF){
      x=-1;
      return ;
  }
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

void insert(int pos){
    int rt=0;
    for(int i=29;i>=0;i--){
        int to=(a[pos]>>i)&1;
        if(!son[rt][to])son[rt][to]=++num,l[num]=r[num]=pos;
        rt=son[rt][to];
        l[rt]=min(l[rt],pos),
        r[rt]=max(r[rt],pos);
    }
}

LL fin(int val,int rt,int dep){
    if(dep==0||l[rt]==r[rt]) return (LL)a[l[rt]];
    int to=1&(val>>dep-1);
    if(son[rt][to])return fin(val,son[rt][to],dep-1);
    else if(son[rt][!to]) return fin(val,son[rt][!to],dep-1);
    else return 0;
}

LL ans=0;
void dfs(int rt,int dep){
    if(dep==0)return ;
    int ls=son[rt][0],rs=son[rt][1];
    if(ls&&rs){
        LL res=2e18;
        for(int i=l[ls];i<=r[ls];i++){
            res=min(res,a[i]^fin(a[i],rs,dep-1));
        }
        ans+=res;
    }
    if(ls)dfs(ls,dep-1);
    if(rs)dfs(rs,dep-1);
}

int main(){
    int n;read(n);
    for(int i=1;i<=n;i++)read(a[i]);
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++)insert(i);

    dfs(0,30);
    printf("%lld\n",ans);
}

Guess you like

Origin blog.csdn.net/jk_chen_acmer/article/details/90679180