P4735 最大异或和

题目
可持久化Trie模板题
维护一棵0/1Trie:

每个节点t[x][y]维护两个值:cntid
cnt :表示到x这个节点所在的根(可理解为时间),y(0/1)出现了几次(前缀和);
id :表示当前数字(x,y)被存在哪个容器中(相当于一个指针)

可持久化Trie:

插入方式与普通Trie基本相同:
对于一个节点,新建一个点表示当前节点:

对于存在的值:t[now][x]={t[last][x].cnt+1,++tot};
对于不存在的值 t[now][x1]=t[last][x1];(直接复制过来)

查询与可持久化线段树类似
---------------------------------------------------------------------------------

对于本题:我们每次对 pos 这个位置插入的是 [1,x] 区间的所有数的异或
对于每一次查询:很容易想到我们要按二进制从高往低贪心。

对于 x 的第 lenx_len,如果在 [p,r] 的所有数的异或中(设为 y )能找到 x_len^1
则说明 y_len^x_len=1,即 ans的第len位可取1,根据贪心,我们应该取

而这题有一个很神奇的地方:

if(t[l][y^1].cnt<t[r][y^1].cnt)
{
// 当前为第len位
return (1<<len)+query(t[l][y^1].id,t[r][y^1].id,len-1,x);
}

只要满足 if 中的条件,则说明在[l,r]的a中(原题目意义下),出现过能改变 len 这一位的数。

而这个神奇的性质就是:
既然它可以使得前缀改变,那它也一定能改变后缀

所以只要满足上述条件,则说明y中有它.

剩下就是一些细节了

code:

#include<bits/stdc++.h>
const int N=3e5+5;
using namespace std;
char c[10];
int n,m,tot;
int rt[N],a[N];
struct Trie{
int cnt,id;
}t[N*30][2];
void ins(int now,int last,int len,int x)
{
if(len<0)return ;
int y=(x>>len)&1;// (当前数字对1的xor)
t[now][y^1]=t[last][y^1];//对于这一位没有的数字,将前面的节点复制过来
t[now][y].id=++tot;
t[now][y].cnt=t[last][y].cnt+1;//对于这一位上的"当前数字",记录前缀和的个数
ins(t[now][y].id,t[last][y].id,len-1,x);
}
int query(int l,int r,int len,int x)
{
if(len<0)return 0;
int y=(x>>len)&1;
if(t[l][y^1].cnt<t[r][y^1].cnt)//y^1在[l,r]之间出现过,根据贪心,取了y^1与y异或一定最优
{
// 当前为第len位
return (1<<len)+query(t[l][y^1].id,t[r][y^1].id,len-1,x);
}
else
{
return query(t[l][y].id,t[r][y].id,len-1,x);
}
}
void work()
{
cin>>n>>m;
rt[0]=++tot;
ins(rt[0],0,25,0);
for(int i=1,x;i<=n;i++)
{
scanf("%d",&x);
a[i]=a[i-1]^x;
rt[i]=++tot;
ins(rt[i],rt[i-1],25,a[i]);
}
for(int i=1,x,l,r,ans;i<=m;i++)
{
scanf("%s",c+1);
if(c[1]=='A')
{
scanf("%d",&x);
rt[++n]=++tot;
a[n]=a[n-1]^x;
ins(rt[n],rt[n-1],25,a[n]);
}
else
{
scanf("%d%d%d",&l,&r,&x);
l--,r--;//序列从0开始
x^=a[n];
if(l==0)
{
ans=query(0,rt[r],25,x);
}
else
{
//l-1:当前可行的区间是[l,r],所以把l-1当作前缀
ans=query(rt[l-1],rt[r],25,x);
}
printf("%d\n",ans);
}
}
}
int main()
{
work();
}
posted @   liuboom  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示