HDU 5536 Chip Factory [Trie]

本文介绍了一种利用Trie树数据结构解决寻找数组中两数之和与另一数进行异或操作得到的最大值的问题。通过构建Trie树并进行遍历,可以有效地找到最大的异或值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#Description
n个数
找出最大的
(ai+aj)xor(ak)
#Algorithm
将所有数的二进制构造出Trie
从高往低构建
比如
11100
00111
10110
就构建成
这里写图片描述
然后每次把枚举ai, aj
把ai,aj从trie中删除 然后再trie中找~(ai+aj)
找的越深 值就越大
#Code

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
const int maxn = 1000 + 10; //n节点个数
const int maxnode = 100000 + 10;
const int sigma_size = 2; //分支个数
int a[maxn];

struct Trie {
    int ch[maxnode][sigma_size]; //节点为i的编号为j节点
    int val[maxnode]; //附加信息
    int sz; //节点总数
    Trie() {
      sz = 1; //构造函数是节点总数是1
      memset(ch[0], 0, sizeof(ch[0]));
      memset(val, 0, sizeof(val));
    }
    void put(int x, int v) {
      int p = 0;
      for(int i = 31; i >= 0; i--) { //为何是31
        int id = (x>>i)&1;
        if(!ch[p][id]) { //节点不存在
          memset(ch[sz], 0, sizeof(ch[sz])); //清空新的节点
          val[sz] = 0; //附加信息
          ch[p][id] = sz++; //孩子数组指向新的节点
        }
        p = ch[p][id]; //往下邹
        val[p] += v; //附加信息为v
      }
    }
    int get(int x) {
      int ans = 0, u = 0;
      for(int i = 31; i >= 0; i--) {
        ans *= 2;
        int id = (x>>i)&1;
        if(ch[u][id] && //有孩子
           val[ch[u][id]]) { //孩子有附加信息
          ans++;
          u = ch[u][id]; //往下走
        }
        else
          u = ch[u][1-id]; //走另外一边
      }
      return ans;
    }
};
void solve() {
  Trie trie;
  memset(a, 0, sizeof(a));
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; ++i) {
    scanf("%d", &a[i]);
    trie.put(a[i], 1);
  }
  int ans = 0;
  for (int i = 0; i < n; ++i) {
    trie.put(a[i], -1);
    for (int j = i + 1; j < n; ++j) {
      trie.put(a[j], -1);
      ans = max(trie.get(~(a[i] + a[j])), ans);
      trie.put(a[j], 1);
    }
    trie.put(a[i], 1);
  }
  printf("%d\n", ans);
}
int main() {
  //freopen("in.txt", "r", stdin);
  int t;
  scanf("%d", &t);
  for (int i = 0; i < t; i++) {
    solve();
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值