AcWing 143. 最大异或对 (异或性质,Trie)

? ? ?

刚开始WA了,数组又开小了,,关于字典树大小的问题,**考虑如果每一个字符都能生成新结点,那么字典树大小就是MAXN*LEN,本题目中数据是1<<31的范围,算上0位**就是32位长度字符串,即MAXN*32;

哦对还看到大佬写的是边插入边查询,这点没想到。

#define int ll
int a[MAXN];
int tot;
int son[MAXN*32][2];
void build(int x)
{
    int p=0;
    for(int k=32;k>=0;--k)
    {
        int tmp=((x&(1ll<<k))==0?0:1);
        if(son[p][tmp]==0) son[p][tmp]=++tot;
        p=son[p][tmp];
    }
}
int solve(int x)
{
    int p=0,ans=0;
    for(int k=32;k>=0;--k)
    {
        int tmp=((x&(1ll<<k))==0?0:1);
        if(son[p][!tmp]) ans|=(1ll<<k),p=son[p][!tmp];
        else p=son[p][tmp];
        if(p==0) break;
    }
    return ans;
}
signed main()
{
    fast;
    int n;cin>>n;
    rpp(i,n)
    {
        cin>>a[i];
        build(a[i]);
    }
    int ans=0;
    rpp(i,n)   ans=max(ans,solve(a[i]));
    cout<<ans<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/Herlo/p/12341716.html

时间: 2024-09-29 17:00:18

AcWing 143. 最大异或对 (异或性质,Trie)的相关文章

AcWing 143. 最大异或对

https://www.acwing.com/problem/content/145 #include <iostream> #include <algorithm> using namespace std; const int N = 100010; int n; int a[N]; class TrieNode { public: TrieNode() {}; TrieNode* children[2]; }; class Trie { public: Trie() { roo

【BZOJ3689】异或之 堆+可持久化Trie树

[BZOJ3689]异或之 Description 给定n个非负整数A[1], A[2], ……, A[n].对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这样共有n*(n-1)/2个新的数.求这些数(不包含A[i])中前k小的数.注:xor对应于pascal中的“xor”,C++中的“^”. Input 第一行2个正整数 n,k,如题所述.以下n行,每行一个非负整数表示A[i]. Output 共一行k个数,表示前k小的数. Samp

bzoj 3261: 最大异或和 (可持久化trie树)

3261: 最大异或和 Time Limit: 10 Sec  Memory Limit: 512 MB Description 给定一个非负整数序列 {a},初始长度为 N.       有   M个操作,有以下两种操作类型: 1 .A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1.2 .Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得: a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少. Inp

bzoj 4017 子序列和的异或以及异或的和

位运算很好的一个性质是可以单独每一位考虑..... 题解请看:http://blog.csdn.net/skywalkert/article/details/45401245 对于异或的和,先枚举位,求所有异或和和中该位为1的有多少个,再乘以该位的大小(2的多少次方). 即单独每一位考虑,每位带的权不一样. 对于和的异或,只需知道每一位中和的改位为1的奇偶性,就可以知道最终的异或值上该位是0还是1. 也是单独考虑每一位,看该位为0或1的条件. 1 /***********************

【BZOJ 4103】 4103: [Thu Summer Camp 2015]异或运算 (可持久化Trie)

4103: [Thu Summer Camp 2015]异或运算 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 474  Solved: 258 Description 给定长度为n的数列X={x1,x2,...,xn}和长度为m的数列Y={y1,y2,...,ym},令矩阵A中第i行第j列的值Aij=xi xor  yj,每次询问给定矩形区域i∈[u,d],j∈[l,r],找出第k大的Aij. Input 第一行包含两个正整数n,m,分别表示两

51nod 1301 集合异或和——异或dp

题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1301 好题!看了TJ才会. 因为是不可重集合,所以当然有前 i 个表示A和B都考虑的前 i 个,新加一个讨论放A.放B.不放. A<B在异或上看就是有一位,它前面的A和B都一样,该位A是0.B是1.该位可以枚举.然后就能dp了. 注意边界细节--和标程对拍真愉快-- #include<iostream> #include<cstdio> #in

bzoj3261: 最大异或和 (可持久化trie树)

题目链接 题解 看到异或和最大就应该想到01 trie树 我们记\(S_i\)为前i项的异或和 那么我们的目的是最大化\(S_n\)^\(x\)^\(S_{j-1}\) \((l <= j <= r)\) (注意是\(j-1\), 所以l和r都要减1) \(S_n\)^\(x\)已经固定, 那么我们可以把\(S_j\)放入trie树搞 那么怎么处理区间呢? 类似主席树 记录一下\([1-i]\)每个节点被多少个数经过 那么两棵trie树相减,就得到了 \([l-r]\)这段区间的信息 然后就是

bzoj4103 [Thu Summer Camp 2015]异或运算(可持久化trie)

内存限制:512 MiB 时间限制:1000 ms 题目描述 给定长度为n的数列X={x1,x2,...,xn}和长度为m的数列Y={y1,y2,...,ym},令矩阵A中第i行第j列的值Aij=xi xor yj,每次询问给定矩形区域i∈[u,d],j∈[l,r],找出第k大的Aij. 输入格式 第一行包含两个正整数n,m,分别表示两个数列的长度 第二行包含n个非负整数xi 第三行包含m个非负整数yj 第四行包含一个正整数p,表示询问次数 随后p行,每行均包含5个正整数,用来描述一次询问,每行

BZOJ3261 最大异或和 (可持久化Trie)

const maxn=600008; len=24; var x,y,z,n,m,tot,lx,i:longint; sum:array[0..maxn] of longint; rt:array[0..maxn] of longint; time,l,r:array[0..maxn*len] of longint; ch:char; procedure insert(x:longint);inline; var p,i:longint; begin rt[lx]:=tot+1; p:=rt[l