比赛 |
round 1『缺混麻酱伞鹊役』 |
评测结果 |
AAAAAAAAAA |
题目名称 |
Xor-MST |
最终得分 |
100 |
用户昵称 |
darkMoon |
运行时间 |
11.357 s |
代码语言 |
C++ |
内存使用 |
68.18 MiB |
提交时间 |
2024-11-21 09:28:47 |
显示代码纯文本
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
using namespace std;
auto mread = [](){int x;scanf("%d", &x);return x;};
const int N = 2e5 + 5;
int n = mread(), a[N], fa[N];
int findfa(int x){
if(x == fa[x]){
return x;
}
return fa[x] = findfa(fa[x]);
}
long long ans = 0;
vector<int> v[N];
pair<int, int> to[N];
// to_i 表示 i 这个连通块能连的最小边,fi 是边权,se 是点
struct tree{
int idx, to[N * 30][2], siz[N * 30], p[N * 30];
void build(){
idx = 0;
to[0][0] = to[0][1] = 0;
return;
}
void push(int id){
int x = 0;
for(int i = 30; i >= 0; i --){
int t = ((a[id] >> i) & 1);
if(to[x][t] == 0){
to[x][t] = ++idx;
to[idx][0] = to[idx][1] = 0;
}
x = to[x][t];
siz[x] ++;
}
p[x] = id;
return;
}
pair<int, int> query(int id){
int ans = 0, x = 0;
for(int i = 30; i >= 0; i --){
int t = ((a[id] >> i) & 1);
if(to[x][t] == 0 || siz[to[x][t]] == 0){
ans += (1 << i);
x = to[x][t ^ 1];
}
else{
x = to[x][t];
}
}
return mp(ans, p[x]);
}
void erase(int id){
int x = 0;
for(int i = 30; i >= 0; i --){
int t = ((a[id] >> i) & 1);
if(to[x][t] == 0){
to[x][t] = ++idx;
to[idx][0] = to[idx][1] = 0;
}
x = to[x][t];
siz[x] --;
}
return;
}
}t;
signed main(){
for(int i = 1; i <= n; i ++){
cin >> a[i];
fa[i] = i;
}
sort(a + 1, a + 1 + n);
int sum = 0;
for(int i = 1; i <= n; i ++){
t.push(i);
}
while(1){
for(int i = 1; i <= n; i ++){
v[i].clear();
}
for(int i = 1; i <= n; i ++){
v[findfa(i)].push_back(i);
to[i] = mp(INT_MAX, 0);
}
for(int i = 1; i <= n; i ++){
if(v[i].size()){
for(int x : v[i]){
t.erase(x);
}
for(int x : v[i]){
to[i] = min(to[i], t.query(x));
}
for(int x : v[i]){
t.push(x);
}
}
}
int tmp = 0;
// tmp 表示有没有连通块向外连边了
for(int i = 1; i <= n; i ++){
if(v[i].size()){
if(to[i].se > 0 && findfa(v[i][0]) != findfa(to[i].se)){
tmp = 1;
fa[findfa(v[i][0])] = findfa(to[i].se);
ans += to[i].fi;
}
}
}
if(tmp == 0){
break;
}
}
printf("%lld", ans);
return 0;
}