51nod 1295 XOR key

本文介绍了一种使用可持久字典树解决区间异或最大值查询问题的方法。通过将数值按位插入到字典树中,并利用可持久化结构进行区间相减,实现了高效的查询算法。

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

给出n个数a1,a2...an(0ai109)m次询问

每次询问给出一个区间[l,r]和一个整数x,询问maxlir{aiai}


考虑不带区间询问的如何解决

我们可以将每个数按照从高位到低位插入到一个字典树中去,每次询问按照当前位在字典树上贪心即可


考虑本题每次询问的是一个区间的数,可以考虑用可持久数据结构解决

仿照主席树的做法,建立一个可持久字典树。

每次询问将rootr,rootl1这两个字典树相减,即可解决本题


代码也很简洁

#include<bits/stdc++.h>
using namespace std;
const int maxn = 51234,bnd = 32;

struct Node{
    int cnt,son[2];
}node[maxn*bnd*2];
int _cnt,root[maxn];
int newnode(){ 
    node[_cnt].cnt= 0;
    node[_cnt].son[0] = node[_cnt].son[1] = -1;
    return _cnt++; 
}

void init(){ _cnt = 0; root[0] = newnode(); }

int arr[maxn],num[bnd];
void ins(int x){ 
    for(int i=0;i<bnd;i++) 
        num[i] = (x>>i) & 1;
    reverse(num,num+bnd);
}
int inser(int o,int pos){
    if(pos > bnd) return -1;
    int st = newnode();
    node[st].cnt = node[o].cnt+1;
    node[st].son[num[pos]^1] = node[o].son[num[pos]^1];
    node[st].son[num[pos]] = inser(node[o].son[num[pos]],pos+1);
    return st;
}

void build(int n){
    for(int i=1;i<=n;i++){
        ins(arr[i]); 
        root[i] = inser(root[i-1],0);
    }
}

int ans;
int gcnt(int st,int p){
    if(st == -1 || node[st].son[p] == -1) return 0;
    return node[node[st].son[p]].cnt;
}
int gnex(int st,int p){
    if(st == -1) return -1;
    return node[st].son[p];
}
void query(int pos,int l,int r){
    if(pos >= bnd) return;
    int nex = 1 ^ num[pos];
    if(gcnt(r,nex) - gcnt(l,nex) == 0)
        nex ^= 1;
    ans = ans * 2 + (nex ^ num[pos]);
    query(pos+1,gnex(l,nex),gnex(r,nex));
}

int que(int v,int l,int r){
    ins(v);
    ans = 0;
    query(0,l,r);
    return ans;
}
int main(){
    int n,m;
    while(~scanf("%d %d",&n,&m)){
        init();
        for(int i=1;i<=n;i++) scanf("%d",&arr[i]);
        build(n);
        int l,r,x;
        while(m--){
            scanf("%d %d %d",&x,&l,&r);
            l++,r++;
            printf("%d\n",que(x,root[l-1],root[r]));
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值