Acwing3485. 最大异或和(trie树)

题目

给定一个非负整数数列 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

  • 输入样例:
3 2
1 2 4
  • 输出样例:
6

代码

import java.util.*;

public class Main {
    static int N=3100010;
    static int n,m,ids=0;
    //trie
    static int[][] tr=new int[N][2];
    //权值
    static int[] cnt=new int[N];
    //异或前缀和
    static int[] s=new int[N];
    //插入数据
    public static void insert(int x,int v) {
        int p=0;
        for(int i=30;i>=0;i--){
            int temp=x>>i&1;
            if(tr[p][temp]==0)tr[p][temp]=++ids;
            p=tr[p][temp];
            cnt[p]+=v;
        }
    }

	//查询
    public static int query(int x) {
        int res=0;
        int p=0;
        for(int i=30;i>=0;i--){
            int temp=x>>i&1;
            if(cnt[tr[p][temp^1]]!=0)
            {
                p=tr[p][temp^1];
                res=res*2+1;
            }else {
                p=tr[p][temp];res*=2;
            }
        }
        return res;

    }



    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
        for (int i = 1; i <= n; i++) {
            int x;
            x = scanner.nextInt();
            s[i] = s[i - 1] ^ x;
        }

        int res = 0;
        insert(s[0], 1);
        for (int i = 1; i <= n; i++) {
            if (i - m - 1 >= 0)
                insert(s[i - m - 1], -1);
            res = Math.max(res, query(s[i]));
            insert(s[i], 1);
        }
        System.out.println(res);
    }
}

思路

分析题目数据大小,强行遍历会超时,trie的树可以在满足调整移动窗口的同时完成题目查询最大异或值的要求,完美符合题意。trie树大家自行了解,想到trie树解决后题目很简单。

你可能感兴趣的:(java算法实录,java,算法,开发语言)