首页 > 其他分享 >trie 树 求最大异或和

trie 树 求最大异或和

时间:2023-03-03 09:11:38浏览次数:28  
标签:最大 trie res son int 异或 数组

题目:
给定一个非负整数数列 a,初始长度为 N。

请在所有长度不超过 M 的连续子数组中,找出子数组异或和的最大值。

子数组的异或和即为子数组中所有元素按位异或得到的结果。

注意:子数组可以为空。

输入格式
第一行包含两个整数 N,M。

第二行包含 N 个整数,其中第 i 个为 ai。

输出格式
输出可以得到的子数组异或和的最大值。

数据范围
对于 20% 的数据,1≤M≤N≤100
对于 50% 的数据,1≤M≤N≤1000
对于 100% 的数据,1≤M≤N≤105,0≤ai≤231−1

本题的关键 是trie 树的建立与删除。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e5+10, M = 31*N;

int n,m;
int son[M][2],idx;
int s[N];
int cnt[M];
void insert(int x,int v)
{
    int p = 0;
    for(int i = 30;i>=0;i--)
    {
        int u = x>>i&1;
        if(!son[p][u]) son[p][u] = ++idx;
        p = son[p][u];
        cnt[p]+=v;//记录能到这个节点的前缀和个数
    }
}

int query(int x)
{
    int p = 0,res =0;
    for(int i = 30; i>=0;i--)
    {
        int u = x>>i&1;
        if(cnt[son[p][!u]])
        {
            p = son[p][!u];
            res = res*2+!u;
        }
        else 
        {
             p = son[p][u];
             res = res*2+u;
        }
    }
    return res;
}
int main()
{
    
    scanf("%d%d",&n,&m);
    int res = 0;
    for(int i = 1; i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        s[i] = s[i-1]^x;
        if(i>1) 
        {
         if(i>m+1) insert(s[i-m-1],-1);
         int t = query(s[i]);
         res = max(res,s[i]^t);
         if(i<=m) res= max(res,s[i]);
        }
        insert(s[i],1);
    }
    cout<<res<<endl;
    return  0;
}

标签:最大,trie,res,son,int,异或,数组
From: https://www.cnblogs.com/freshman666/p/17174366.html

相关文章