round-888-div3

本文介绍了如何使用0-1字典树解决Codeforces1851F问题,通过贪心策略维护异或极值,通过逐位比较插入节点并计算最大值,时间复杂度为O(n),空间复杂度未知。涉及到的数据结构包括TrieNode和Trie类。

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

题目 codeforce 1851F
数据结构:0-1字典树
算法:局部贪心
作用:维护异或极值,从左到右依次插入,判断极值。

解题思路

  1. 根据公式,推导性质。 ( a i ⊕ x ) & ( a j ⊕ x ) (a_i\oplus x) \& (a_j\oplus x) (aix)&(ajx) 从高位到低位依次贪心,如果两个数的相同,则可以转化位1,对应x上的数应该取反。举例如果ai和aj的某位都是1,则x取0,经过异或,两个都变成1,然后经过与运算,还是1。相反ai和aj都是0,则x取1。
  2. 使用0-1字典树,遍历插入,并计算最大值。
    时间复杂度:O(n)
    空间复杂度:unknown

相似题目:力扣421,数组中两个数的最大异或值

参考代码

class TrieNode:
    def __init__(self):
        self.children = [None] * 2
        self.idx = -1


class Trie:

    def __init__(self, h):
        self.h = h
        self.root = TrieNode()

    def insert(self, num, idx):
        node = self.root
        for i in range(self.h - 1, -1, -1):
            lr = (num >> i) & 1
            if node.children[lr] is None:
                node.children[lr] = TrieNode()
            node = node.children[lr]
        node.idx = idx

    def minimum_xor(self, num):
        mx = 0
        mask = 0

        node = self.root
        for i in range(self.h - 1, -1, -1):
            lr = (num >> i) & 1
            if node.children[lr]:
                node = node.children[lr]
                if lr == 0:
                    mask |= (1 << i)
                mx |= (1 << i)
            elif node.children[lr ^ 1]:
                node = node.children[lr ^ 1]
            else:
                print('break')
                break
        return mx, mask, node.idx


def solve(n, k, nums):
    trie = Trie(k)
    trie.insert(nums[0], 0)
    ans = 0
    l, r, x = 0, 1, 0
    for j, num in enumerate(nums[1:]):
        mx, mask, i = trie.minimum_xor(num)
        if mx > ans:
            ans = mx
            l, r, x = i, j + 1, mask
        trie.insert(num, j + 1)
    print(l + 1, r + 1, x)
    # print(f"max: {(nums[l] ^ x) & (nums[r] ^ x)}")


def main():
    tcn = int(input())
    for _ in range(tcn):
        n, k = map(int, input().split())
        nums = list(map(int, input().split()))
        solve(n, k, nums)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值