[十二省联考2019]异或粽子
XXXVI.[十二省联考2019]异或粽子
好像对可持久化结构有了新的认识(
首先,我们考虑,区间异或和,可以直接被转换为前缀异或和的异或和,即 。于是我们考虑对于每个 找到与其异或起来最大的 。
显然,可以建一棵可持久化01trie,每个位置的trie上记录了 ,然后只需用经典套路找出对于 最大的 即可。
现在考虑回答询问。依照某种套路,我们可以用一个堆维护对于每个 最大的 ,然后每次从堆中找到最大的 ,并且把这个 对应的次大的 找出来。
于是我们需要支持动态地从01trie上删数。
在普通01trie上这是很好做的;但是这里可持久化了,要是直接减少区间中数的个数可能会影响到之后的trie。
于是我们便想到,减少一个数时,额外再拷贝一条新链出来就行了。(只不过这样空间复杂度就是 的,但此题空间一个 G
,可以随意挥霍)
于是便做完了,时间复杂度 。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef unsigned int ui;
typedef long long ll;
int n,m,cnt,rt[500100];
struct Trie{
int ch[2],sz;
}t[30001000];
const int LG=31;
ll res;
ui a[500100];
void ins(int &x,int y,ui z,int del,int dep){
x=++cnt,t[x]=t[y],t[x].sz+=del;
if(dep==-1)return;
ins(t[x].ch[(z>>dep)&1],t[y].ch[(z>>dep)&1],z,del,dep-1);
}
ui findmx(int x,ui z,int dep){
if(dep==-1)return 0;
// printf("%d:(%d,%d):%u,%d\n",x,ch[x][0],ch[x][1],z,dep);
if(t[t[x].ch[!((z>>dep)&1)]].sz)return findmx(t[x].ch[!((z>>dep)&1)],z,dep-1)+(1<<dep);
return findmx(t[x].ch[(z>>dep)&1],z,dep-1);
}
void iterate(int x,int dep,ui val){
if(!x)return;
if(dep==-1){printf("(%u:%d)",val,t[x].sz);return;}
iterate(t[x].ch[0],dep-1,val),iterate(t[x].ch[1],dep-1,val+(1<<dep));
}
priority_queue<pair<ui,int> >q;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%u",&a[i]),a[i]^=a[i-1],ins(rt[i],rt[i-1],a[i-1],1,LG),q.push(make_pair(findmx(rt[i],a[i],LG),i));
while(m--){
ui z=q.top().first;int i=q.top().second;
q.pop();res+=z,ins(rt[i],rt[i],z^a[i],-1,LG);
if(t[rt[i]].sz)q.push(make_pair(findmx(rt[i],a[i],LG),i));
}
printf("%lld\n",res);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?