首页 > 其他分享 >可持久化字典树

可持久化字典树

时间:2023-01-13 00:33:19浏览次数:54  
标签:rt opt cnt 持久 int nex 字典

在介绍可持久化字典树之前,我们先要说一下01字典树。

01字典树的一个功能是:

  1. 向当前集合中插入一个正整数。
  2. 查询当前集合中异或上x后最大的那个数。

接下来介绍一下这两个操作是如何实现的:

  1. 插入x,我们把x看做一个二进制数,从高位向低位遍历,根据当前位是0或者1,把Tire的枝叶伸向不同的方向。
  2. 根据异或的性质,我们同样是从高位到低位遍历x的二进制串,若x当前位为1且存在0的枝叶,那就去0那一条枝叶,总之就是尽量与x的当前位取反,这样可以贪心的得到正解。

那如果我想查询区间 \([l, r]\) 的数字与x异或后最大的那个数,怎么办?求异或的这个问题,是通过字典树来解决的,所以区间询问这个问题,就是典中典的可持久化数据结构应用问题了。如果你真正的学会了可持久化线段树的话,那么YY一下也就能改出可持久化字典树的代码了。

​ 来道典题BZOJ4546. CodeChef XRQRS

#include <bits/stdc++.h>

using namespace std;
const int N = 500005, M = 24;
int m;
int rt[N], tot = 0, cnt = 0; //rt:版本数组,tot动态开点,cnt是版本编号。

struct Trie {
    int nex[N * M][2];
    int sum[N * M];
    void insert(int &p, int old, int d, int x) //p当前版本编号,d在枚举二进制。
    {
        p = ++ tot;
        memcpy(nex[p], nex[old], sizeof nex[p]);
        sum[p] = sum[old] + 1;
        if(d < 0)
            return;
        if(x >> (d - 1) & 1)
            insert(nex[p][1], nex[old][1], d - 1, x);
        else
            insert(nex[p][0], nex[old][0], d - 1, x);
    }
    int query_max(int v1, int v2, int d, int x)
    {
        if(d < 0)
            return 0;
        int flag = (x >> (d - 1) & 1);
        if(sum[nex[v2][flag ^ 1]] - sum[nex[v1][flag ^ 1]] > 0)
            return (1 << (d - 1)) + query_max(nex[v1][flag ^ 1], nex[v2][flag ^ 1], d - 1, x);
        else
            return query_max(nex[v1][flag], nex[v2][flag], d - 1, x);
    }
    int query_num(int v1, int v2, int d, int now, int x)
    {
        if(d < 0)
            return 0;
        if(now + (1 << (d - 1)) <= x)
            return sum[nex[v2][0]] - sum[nex[v1][0]] + query_num(nex[v1][1], nex[v2][1], d - 1, now + (1 << (d - 1)), x);
        else
            return query_num(nex[v1][0], nex[v2][0], d - 1, now, x);
    }
    int query_kth(int v1, int v2, int d, int k)
    {
        if(d < 0)
            return 0;
        int sz = sum[nex[v2][0]] - sum[nex[v1][0]];
        if(sz >= k)
            return query_kth(nex[v1][0], nex[v2][0], d - 1, k);
        else
            return (1 << (d - 1)) + query_kth(nex[v1][1], nex[v2][1], d - 1, k - sz);
    }
};
Trie T1;

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    int m;
    cin >> m; 
    while(m --)
    {
        int opt;
        cin >> opt;
        if(opt == 1)
        {
            int x; cin >> x;
            cnt ++;
            T1.insert(rt[cnt], rt[cnt - 1], 19, x);
        }
        else if(opt == 2)
        {
            int l, r, x;
            cin >> l >> r >> x;
            int s = T1.query_max(rt[l - 1], rt[r], 19, x);
            cout << (s ^ x) << '\n';
        }
        else if(opt == 3)
        {
            int k;
            cin >> k;
            cnt -= k;
            tot = rt[cnt + 1] - 1;
        }
        else if(opt == 4)
        {
            int l, r, x;
            cin >> l >> r >> x;
            cout << T1.query_num(rt[l - 1], rt[r], 19, 0, x) << '\n';
        }
        else
        {
            int l, r, k;
            cin >> l >> r >> k;
            cout << T1.query_kth(rt[l - 1], rt[r], 19, k) << '\n';
        }
    }
}

标签:rt,opt,cnt,持久,int,nex,字典
From: https://www.cnblogs.com/DM11/p/17048354.html

相关文章

  • 字典树(Trie)
    字典树Trie树,即字典树,是一种树形结构。典型应用是用于统计和排序大量的字符串前缀来减少查询时间,最大限度地减少无谓的字符串比较。Trie树的核心思想是空间换时间。利......
  • E. Beautiful Subarrays(01字典树)
    Problem-E-Codeforces题意:给一个长度为n的数组a,问有多少个连续的子数组的异或和大于等于k思路:01字典树建立前缀异或和数组,题目变为有多少个$a_iˆa_j(1......
  • Trie树 (字典树)
    什么是trie树trie树是一种用来查找字符串的树形结构,利用字符串公共信息把多个字符串存储成一棵树,节约内存,加快检索速度这是一棵字典树trie树的性质1.根节点为空......
  • 48-Docker-多容器数据共享及持久化
    Docker镜像数据读写原理Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层如果运行中的容器修改了现有的一个已经存在的文件,那......
  • python列表里的字典元素去重
    去重:fromfunctoolsimportreduce#导入排序模块#列表里的字典元素去重复deflist_dict_duplicate_removal(data_list):run_function=lambdax,y:xifyi......
  • Redis缓存何以一枝独秀?(2) —— 聊聊Redis的数据过期、数据淘汰以及数据持久化的实现
    大家好,又见面了。本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面。如果感兴趣,欢迎关注以获取后续更新。上......
  • 数据结构——字典树
    NO.1定义字典树又称单词查找树,\(Trie\)树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文......
  • Redis-单机数据库-RDB持久化
    RDB文件结构RDB文件的最开头是 REDIS 部分,这个部分的长度为 5 字节,保存着 "REDIS" 五个字符。通过这五个字符,程序可以在载入文件时,快速检查所载入的文件是否......
  • jeecgBoot对象字典解析
    接口:interface CommonService声明:publicJSONObjectconvertObjDict(Objectobj,booleanisIgnore,String...columns);实现类:classCommonServiceImplimplements......
  • 元组和字典
    一.元组1.与列表类似,区别在于:①元组用小括号()定义,②元组的元素不能修改2.操作:①交换变量的值        ②元组的方法  .count()和.index()     ......