可持久化01Trie [Heoi2013]Alo

本文介绍了一个VRMMORPG游戏Arithmetic and Logistic Online中的数学谜题,通过使用可持久化01 Trie算法解决宝石融合问题,以最大化生成宝石的能量密度。

问题 I: [Heoi2013]Alo
时间限制: 3 Sec 内存限制: 256 MB
提交: 64 解决: 24
[提交][状态][讨论版]
题目描述
Welcome to ALO ( Arithmetic and Logistic Online)。这是一个VR MMORPG ,
如名字所见,到处充满了数学的谜题。
现在你拥有n颗宝石,每颗宝石有一个能量密度,记为ai,这些宝石的能量
密度两两不同。现在你可以选取连续的一些宝石(必须多于一个)进行融合,设为 ai, ai+1, …, a j,则融合而成的宝石的能量密度为这些宝石中能量密度的次大值
与其他任意一颗宝石的能量密度按位异或的值,即,设该段宝石能量密度次大值
为k,则生成的宝石的能量密度为max{k xor ap | ap ≠ k , i ≤ p ≤ j}。
现在你需要知道你怎么选取需要融合的宝石,才能使生成的宝石能量密度最大。

输入
第一行,一个整数 n,表示宝石个数。
第二行, n个整数,分别表示a1至an,表示每颗宝石的能量密度,保证对于i ≠ j有 ai ≠ aj。

输出
输出一行一个整数,表示最大能生成的宝石能量密度。

样例输入
5
9 2 1 4 7
样例输出
14

提示
【样例解释】
选择区间[1,5],最大值为 7 xor 9。
对于 100%的数据有 1 ≤ n ≤ 50000, 0 ≤ ai ≤ 10^9

可持久化01Trie正式入坑。。其实和主席树整体上是一样的,但这里就区别于普通Trie树了。普通的是在不同的地方建一条新枝。可持久的依然是完全新建一条链。
这道题利用的区间异或的最大值,就是在这个区间一位位贪心地向下找。做减法判断区间里是否有能对答案产生贡献的元素,有就选就选,并向相应的子节点推进。

这道题其他的地方:次大值。。考虑把权值排序后从大到小插入一个set。所以当前set里所有位置对应的值都是比当前元素大的。那么他是次大的区间就是前驱的前驱位置+1,后继的后继的位置-1.

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <set>
#define N 50005
#define inf 1000000000
using namespace std;
int n,ans,xp[31];
struct node{int h,id;}a[N];
set<int> st;
namespace TRIE
{
    struct trie
    {
        trie* ch[2];
        int sum;
        trie(){sum=0;ch[0]=ch[1]=NULL;}
    }*null=new trie(),*root[N];
    trie* newtrie()
    {
        trie* o=new trie();
        o->ch[0]=o->ch[1]=null;
        return o;
    }
    void ins(trie* &now,trie* pre,int x,int i)
    {
        if(i<0)return;
        int k=x&xp[i];k>>=i;
        now->ch[k^1]=pre->ch[k^1];
        now->ch[k]=newtrie();
        now->ch[k]->sum=pre->ch[k]->sum+1;
        ins(now->ch[k],pre->ch[k],x,i-1);
    }
    int q(trie* l,trie* r,int x)
    {
        int tmp=0;
        for(int i=30;i>=0;i--)
        {
            int k=x&xp[i];k>>=i;
            if(r->ch[k^1]->sum-l->ch[k^1]->sum)
                l=l->ch[k^1],r=r->ch[k^1],tmp+=xp[i];
            else l=l->ch[k],r=r->ch[k];
        }
        return tmp;
    }
}
using namespace TRIE;
inline bool cmp(node a,node b){return a.h>b.h;}
int main()
{
    scanf("%d",&n);
    null->ch[0]=null->ch[1]=null;
    xp[0]=1;for(int i=1;i<=30;i++)xp[i]=xp[i-1]<<1;
    for(int i=1;i<=n;i++)scanf("%d",&a[i].h),a[i].id=i;
    for(int i=0;i<=n;i++)root[i]=newtrie();
    for(int i=1;i<=n;i++)ins(root[i],root[i-1],a[i].h,30);
    sort(a+1,a+n+1,cmp);
    st.insert(-1);st.insert(0);
    st.insert(n+1);st.insert(n+2);
    st.insert(a[1].id);
    set<int>::iterator it1,it2; 
    for(int i=2,l,r;i<=n;i++)
    {
        st.insert(a[i].id);
        it1=it2=st.find(a[i].id);
        it1--;it1--;l=*it1+1;l=max(l,1);
        it2++;it2++;r=*it2-1;r=min(n,r);
        if(l!=r)ans=max(ans,q(root[l-1],root[r],a[i].h));
    }
    printf("%d\n",ans);
}
### 可持久化数据结构的概念及其实现 #### 什么是可持久化数据结构? 可持久化数据结构是一种允许访问其任何历史版本的数据结构。这种特性使得它在某些场景下非常有用,比如需要频繁回溯或者比较不同状态的应用程序中。为了支持这一功能,可持久化数据结构通常会通过共享未修改部分的方式来减少内存消耗[^1]。 #### 如何实现可持久化数据结构? ##### 不可变性原则 实现可持久化的基础在于保持数据结构的不可变性。每次更新操作实际上并不改变原有数据结构,而是创建一个新的版本,其中新旧版本之间尽可能多地共享相同的部分以节省空间。 ##### 版本管理机制 对于每一次的操作(如插入、删除),都需要记录该次变化形成的新版本号,并且能够依据此版本号恢复对应的状态。这可以通过路径复制技术完成,在不破坏原结构的前提下构建新的节点链路[^2]。 #### 应用实例分析——可持久化 Trie 树 作为一种典型的例子,可持久化Trie被广泛应用于字符串匹配等领域。当向一棵已存在的Trie树添加一个单词时,仅需沿着可能影响到的分支新建若干个节点即可,其余不变区域依旧指向原来的节点地址,从而实现了高效的空间利用率提升以及快速查询能力增强的效果。 以下是基于 Python 的简单模拟代码展示如何构造基本形式上的可持久化字典树: ```python class PersistentTrieNode: def __init__(self, value=None): self.children = {} self.value = value def insert(root_versions, word, version_id=0): root = root_versions[version_id].copy() node_stack = [] current_node = root for char in word: if char not in current_node['children']: new_child = {'value': None, 'children': {}} current_node['children'][char] = len(node_stack) node_stack.append(new_child) index = current_node['children'].get(char) next_node = node_stack[index] if isinstance(index, int) else {} node_stack.append(next_node.copy()) current_node = next_node current_node['value'] = True root_versions.append({k:v.copy() for k,v in zip(['root'], [node_stack[-1]])}) ``` 上述代码片段展示了如何维护多个版本的根节点列表 `root_versions` ,并通过深拷贝确保每一步骤都独立存在而不互相干扰。 #### 数据校验中的作用 除了作为纯粹的数据存储工具外,可持久化数据结构还可以与其他技术相结合用于更复杂的场合。例如,在分布式文件系统的元数据管理过程中引入数据校验方法,则可以进一步加强整个体系面对硬件故障等情况下的稳定性表现[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值