牛客练习赛81 小Q与彼岸花 (分块+可持久化01trie)
题意:
题解:因为这个题目是弱化以后的,正常的范围是5e4 .
看了官方题解去学习了一波可持久化01trie然后回来把这个题补完。
可持久数据结构其实就是我们的数据结构的内容会不断发生变化,而我们还要查询以前的历史版本,比如某个区间的情况。
听名字可以听出来,可持久化01trie跟可持久化线段树差不多的效果,对于01字典树来说,可以指定查询 l−rl-rl−r 范围内的数组成的字典树。
但是针对于这个题目我们直接使用可持久化01trie进行维护,时间还是不能被允许的,所以说, 我们还需要去继续优化。
如何优化呢? 分块!
我们用数组ans[x][y]ans[x][y]ans[x][y]预处理出来 块x到块y之间的区间任意两数的最大异或值。
时间复杂度呢?
我们把数组分成大小为n\sqrt{n}n的块,那么可以分成(n−1)/n+1(n-1)/\sqrt{n}+1(n−1)/n+1个块
所以预处理的复杂度为:
O(n∗n∗n∗log(amax))O(\sqrt{n}*\sqrt{n}*\sqrt{n}*log(a_{max}) )O(n∗n∗n∗log(amax)) (类似于区间求解众数–强制在线)
应该没错。。。
for(int i=1;i<=sumblocks;i++){for(int j=i;j<=sumblocks;j++){int nowmax=ans[i][j-1];for(int k=(j-1)*sz+1;k<=min(n,j*sz);k++){int res=query(rt[min(j*sz,n)],a[k],(i-1)*sz+1);nowmax=max(nowmax,res);}ans[i][j]=nowmax;}
}
然后对于每次查询,如果l和r属于同一个块之间,那么我们直接暴力即可
那么如果不在同一个块呢,那么就跟最简单的分块一样了,先让最大值等于中间完整的块,然后我们暴力处理一下两边不全的块并不断更新最大值,然后返回最大值即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e6+10;int ans[300][300];
int a[maxn],buck[maxn];
int rt[maxn];
int sz,idx;
int trie[maxn*20][2];
int max_id[maxn];void ins(int x,int pre,int now){for(int i=12;i>=0;i--){max_id[now]=x;int val=(a[x]>>i)&1;trie[now][val^1]=trie[pre][val^1];trie[now][val]=++idx;now=idx;pre=trie[pre][val];}max_id[now]=x;
}int query(int root,int C,int L){int p=root;for(int i=12;i>=0;i--){int val=(C>>i)&1;if(max_id[trie[p][val^1]]>=L) p=trie[p][val^1];else p=trie[p][val];}return C^a[max_id[p]];
}int get_block(int x){return (x-1)/sz+1;
}int sol(int l,int r){int st=get_block(l);int ed=get_block(r);if(st==ed){int imax=0;for(int i=l;i<=r;i++){imax=max(imax,query(rt[r],a[i],l));}return imax;}else{int imax=ans[st+1][ed-1];//cout<<"debug "<<imax<<endl;for(int i=l;i<=st*sz;i++){imax=max(imax,query(rt[r],a[i],l));}for(int i=(ed-1)*sz+1;i<=r;i++){imax=max(imax,query(rt[r],a[i],l));}return imax;}
}int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int n,m;cin>>n>>m;sz=sqrt(n);for(int i=1;i<=n;i++){cin>>a[i];rt[i]=++idx;ins(i,rt[i-1],rt[i]);}int sumblocks=(n-1)/sz+1;for(int i=1;i<=sumblocks;i++){for(int j=i;j<=sumblocks;j++){int nowmax=ans[i][j-1];for(int k=(j-1)*sz+1;k<=min(n,j*sz);k++){int res=query(rt[min(j*sz,n)],a[k],(i-1)*sz+1);nowmax=max(nowmax,res);}ans[i][j]=nowmax;}}while(m--){int l,r;cin>>l>>r;int xxx=sol(l,r);cout<<xxx<<endl;}return 0;}
牛客练习赛81 小Q与彼岸花 (分块+可持久化01trie)相关推荐
- 牛客练习赛81 B. 小 Q 与彼岸花(FWT nlogn做法)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Weblink https://ac.nowcoder.com/acm/contest/11171/B ...
- 牛客练习赛81 E. 小 Q 与函数求和 1( “简单莫比乌斯反演” ,欧拉函数性质)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 牛客练习赛81 E. 小 Q 与函数求和 1( "简单莫比乌斯反演" ) Prob ...
- 小 Q 与树(dsu on tree + segment tree)牛客练习赛 81 D
小 Q 与树 给定一棵带权的树,每条边的距离都为111,要我们求∑u=1n∑v=1nmin(au,av)dis(u,v)\sum\limits_{u = 1} ^{n} \sum\limits_{v ...
- 小 Q 与函数求和 1(牛客练习赛 81 E)
小 Q 与函数求和 1 ∑i=1n∑j=1nϕ(ijgcd(i,j)K)∑i=1n∑j=1ngcd(i,j)Kϕ(ij)∑i=1n∑j=1ngcd(i,j)Kϕ(i)ϕ(j)gcd(i,j)ϕ ...
- 牛客练习赛56 小魂和他的数列
小魂和他的数列 题目链接 题目大意 给出一个数列,让求长度为k的严格递增子序列有多少个 怎么做呢? 显然dp 这个是很好想的 for (int i= 1; i <= n; i ++ ){dp[i ...
- 牛客练习赛59 小松鼠吃松果(优化dp二维偏序)
小松鼠吃松果 非常nicenicenice的一道题 首先考虑dpdpdp 容易想到按照时间来排序 然后定义dp[i]dp[i]dp[i]为考虑前iii个果子且吃掉第iii个的最大价值 那么每次都去前面 ...
- 牛客练习赛79E小G的数学难题
https://ac.nowcoder.com/acm/contest/11169/E 挺有意思的一道题 可以考虑放缩 可以把每个aia_iai放大,若仍然满足条件,那原问题也满足条件 同理把每个b ...
- 牛客练习赛77 小G的约数(整除分块)
其中 1 有 n 个,2 有 n/2 个.......可以发现 :所以只要在一定时间内解决即可,由于可以利用整除分块解决 ,所以两遍递归即可 ll go(ll n) {return n*(n+1)/2 ...
- 牛客练习赛75 D 减数游戏(队列优化(需要取模的)堆)
牛客练习赛75 D 减数游戏 思路:写一下式子可以发每次选择最小的两个数进行操作,最后得到的答案会是最大的,那我们可以将它放进一个最小堆中来维护,但是里面的数是需要取模的,当它取模的时候,将会变小.那 ...
最新文章
- 收藏 | 卷积神经网络 C++ 从零开始实现
- 笔记-项目沟通管理-沟通管理计划
- SpringBoot项目中静态资源加载失败,那可能是自定义配置类继承了WebMvcConfigurationSupport这个类
- java 配置信息_[Java教程]java 配置信息类 Properties 的简单使用
- 19-爬虫之scrapy框架大文件下载06
- linux命令 su和sudo,Linux中sudo和su的区别
- C++中提高程序运行效率的方法集合
- 计算机基础三级,三级数据库计算机基础知识
- 用maven编译spark2.1.0
- 《深入浅出struts》读书笔记(3)
- kafka 修改分区_kafka分区
- 搞学术不完全指北【包括谷歌学术镜像、论文工具、Wiki、SCI-HUB文献下载、翻译等】
- 用友NC 用户名登录设置步骤
- 第二十一章 异步编程
- 大疆FPGA/芯片开发工程师(B卷)笔试题(含详解)
- Android系统控件获取自定义属性
- MPC系列:Beaver三元组和BMR协议
- 主板有电无法启动_电脑主板有电 但是就是开不了机
- C/C++实现strcpy和strcat两个功能
- 在电路中运用叠加定理时,储能元件(电容,电感)的初始值只能计算一次