可持久化字典树

可持久化字典树与可持久化线段树类似。

解决的问题都是类似于“有限制的前缀和”,或二维问题。

而可持久化字典树更多的是解决异或问题,即运用01字典树。

解决异或最大问题,贪心地在字典树上选择。

例题

  1. 最大异或和

前缀异或和把最大的区间异或和转化成单点。

想要与 x 异或后最大,就从高到低 x 在二进制上的每一位,贪心的查找在这一位能不能取到与 x 相反的值。

查找:设合法的吗,与 x 异或值最大的数为ans。因为从高到低枚举每一位,所以 ans 的前缀已经知道,当前这一位加上后的ans 也可以求出。在字典树上查一下,如果有 ans 为前缀的数,那 ans就是合法的。这里的查找实际上是检验贪心的取法会不会在后面出现问题。(取不到)

单点有 l,r 的限制,就用可持久化来解决。

#include<bits/stdc++.h>
using namespace std;
int n,m;
const int MAXN=6e5+5;
int a[MAXN],s[MAXN];
int rt[MAXN];
int ch[MAXN*30][2],cnt[MAXN*30];
int tot;
void insert(int &u,int t,int x){//t:从右往左第t位
    // printf("%d %d %d %d\n",u,t,x,id);
    cnt[++tot]=cnt[u]+1;
    if(t<0) {u=tot;return;}
    ch[tot][0]=ch[u][0];
    ch[tot][1]=ch[u][1];
    u=tot;
    int y=(x>>t)&1;
    insert(ch[u][y],t-1,x);
}
int ask(int u,int v,int t,int x){
    if(t<0) return 0;
    int y=(x>>t)&1;
    if(cnt[ch[v][!y]]>cnt[ch[u][!y]])   return (1<<t)+ask(ch[u][!y],ch[v][!y],t-1,x);
    else    return ask(ch[u][y],ch[v][y],t-1,x);
}
int main(){
    // freopen("1.in","r",stdin);
    // freopen("1.out","w",stdout);
    scanf("%d%d",&n,&m);
    insert(rt[0],25,0);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        s[i]=(s[i-1]^a[i]);
        rt[i]=rt[i-1];
        insert(rt[i],25,s[i]);
        // printf("A\n");
    }
    insert(rt[0],25,0);
    for(int i=1;i<=m;i++){
        char op;
        int l,r,x;
        scanf("\n%c",&op);
        if(op=='A'){
            scanf("%d",&x);
            n++;
            s[n]=(s[n-1]^x);rt[n]=rt[n-1];
            insert(rt[n],25,s[n]);
        }else{
            scanf("%d%d%d",&l,&r,&x);
            l--,r--;
            x^=s[n];
            if(l==0)    printf("%d\n",ask(0,rt[r],25,x));
            else    printf("%d\n",ask(rt[l-1],rt[r],25,x));
        }
    }
    return 0;
}
  1. 美味

这道题和模板题很像,但其实运用的只是字典树的思想。更重要的是这道题提供了一种新的01字典树的理解方式。

通常我们看字典树,一个节点表示的就是它到根节点所组成的数字/字符串。

但还有一种思路,一个节点,若它的前缀是 s,到叶子节点的距离为 x.那这个节点可以表示一个区间 [s,s+(1<<x)1].

posted @   bwartist  阅读(79)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示