BZOJ 2741 L (可持久化01Trie+分块)
题目大意:给你一个序列,共有$q$个询问,每次询问区间$[L,R]$内最大连续字段异或和,强制在线,$n<=12000,m<=5000$
有个细节没处理好$WA$了好久..还有一次$ans$没清零
先对序列建出可持久化$01Trie$
分块预处理出,任意两块所覆盖区域的最大$xor$和,枚举右侧块内的每个数,然后在$01Trie$里查找即可,预处理总时间$O(n \sqrt n)$
对于每次询问,中间部分的答案可以$O(1)$得到
边界情况,左侧不完整块内的每个数都要分别作为区间左端点和右端点在$01Trie$里查找最大值
右侧不完整块内的每个数作为区间右端点在01Trie里查找最大值即可,因为一旦出现它作为左端点的情况,它右面的数一定会作为右端点查询到它
时间$O(q\sqrt n+n\sqrt n)$
数据还挺强的
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 12100
#define N2 420100
#define M1 120
#define ll long long
#define dd double
#define uint unsigned int
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
} int n,m,sq,tq;
uint bin[]; struct Trie{
int ch[N2][],num[N2],root[N1],tot;
void build()
{
root[]=tot=;int x=;
for(int i=;i>=;i--){
ch[x][]=++tot;
x=ch[x][],num[x]=;
}
}
void insert(uint s,int rt1,int rt2,int w)
{
int x,y,p;
y=root[rt1];
x=root[rt2]=++tot;
for(int i=;i>=;i--){
p=(s&bin[i])?:;
ch[x][p]=++tot;
ch[x][p^]=ch[y][p^];
num[ch[x][p]]=num[ch[y][p]]+w;
x=ch[x][p],y=ch[y][p];
}
}
uint query(uint s,int l,int r)
{
int x,y,p;uint ans=;
x=root[r];
y=l<?:root[l];
for(int i=;i>=;i--){
p=(s&bin[i])?:;
if(num[ch[x][p^]]-num[ch[y][p^]]>){
x=ch[x][p^],y=ch[y][p^];
ans|=bin[i];
}else if(num[ch[x][p]]-num[ch[y][p]]>){
x=ch[x][p],y=ch[y][p];
}else break;
}return ans;
}
}T; uint a[N1],pa[N1];
uint s1[M1][M1];
int L[M1],R[M1]; int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=;i++)
bin[i]=(<<i);
int x,y;
T.build();
for(int i=;i<=n;i++)
{
a[i]=gint();
pa[i]=pa[i-]^a[i];
T.insert(pa[i],i-,i,);
}
sq=sqrt(n);tq=n/sq;
for(int i=;i<=tq+;i++)
L[i]=(i-)*sq+,R[i]=min(n,i*sq);
for(int i=;i<=tq;i++)
for(int j=i;j<=tq;j++)
{
s1[i][j]=s1[i][j-];
for(int k=L[j];k<=R[j];k++)
s1[i][j]=max(s1[i][j],T.query(pa[k],L[i]-,k-));
}
uint ans=;int px,py;
for(int j=;j<=m;j++)
{
x=gint(),y=gint();
x=(ans+x)%n+,y=(ans+y)%n+;
if(x>y) swap(x,y);
px=(x-)/sq+,py=(y-)/sq+;
if(px!=py){
ans=s1[px+][py-];
for(int i=x;i<=R[px];i++)
ans=max(ans,T.query(pa[i],x-,i-));
for(int i=x-;i<=R[px]-;i++)
ans=max(ans,T.query(pa[i],i,y));
for(int i=L[py];i<=y;i++)
ans=max(ans,T.query(pa[i],x-,i-));
}else{
ans=;
for(int i=x;i<=y;i++)
ans=max(ans,T.query(pa[i],x-,i-));
}
printf("%u\n",ans);
}
return ;
}
BZOJ 2741 L (可持久化01Trie+分块)的更多相关文章
- BZOJ 2741: 【FOTILE模拟赛】L(可持久化Trie+分块)
传送门 解题思路 首先求出前缀异或和,那么问题就转化成了区间内选两个数使得其异或和最大.数据范围不是很大考虑分块,设\(f[x][i]\)表示第\(x\)块开头到\(i\)这个位置与\(a[i]\)异 ...
- 2018.09.30 bzoj2741: 【FOTILE模拟赛】L(分块+可持久化01trie)
传送门 数据结构经典题. 首先考虑另外一种询问方式. 已知权值val,在区间[1,n][1,n][1,n]中找一个数使得valvalval^a[i]a[i]a[i]最大. 这个可以直接01trie. ...
- bzoj 4137 [FJOI2015]火星商店问题——线段树分治+可持久化01trie树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4137 关于可持久化01trie树:https://www.cnblogs.com/LadyL ...
- BZOJ 4103 [Thusc 2015]异或运算 (可持久化01Trie+二分)
题目大意:给你一个长方形矩阵,位置$i,j$上的数是$a_{i}\;xor\;b_{j}$,求某个子矩阵内第$K$大的值 最先想的是二分答案然后验证,然而是$O(qnlogmloga_{i})$,不出 ...
- BZOJ 3689 异或之 (可持久化01Trie+堆)
题目大意:给你一个序列,求出第$K$大的两两异或值 先建出来可持久化$01Trie$ 用一个$set$/堆存结构体,存某个异或对$<i,j>$的第二关键字$j$,以及$ai\;xor\;a ...
- BZOJ 3261 最大异或和 (可持久化01Trie)
题目大意:让你维护一个序列,支持在序列末插入一个数,支持询问$[l,r]$区间内选择一个位置$p$,使$xor\sum_{i=p}^{n}a_{i}$最大 可持久化$01Trie$裸题,把 区间异或和 ...
- ⌈洛谷4735⌋⌈BZOJ3261⌋最大异或和【可持久化01Trie】
题目链接 [BZOJ传送门] [洛谷传送门] 题解 终于学会了可持久化trie树了.感觉并不是特别的难. 因为可持久化,那么我们就考虑动态开点的trie树. 都知道异或操作是有传递性的,那么我们就维护 ...
- BZOJ 3744 Gty的妹子序列 (分块+树状数组+主席树)
题面传送门 题目大意:给你一个序列,多次询问,每次取出一段连续的子序列$[l,r]$,询问这段子序列的逆序对个数,强制在线 很熟悉的分块套路啊,和很多可持久化01Trie的题目类似,用分块预处理出贡献 ...
- 2019.01.13 bzoj4137: [FJOI2015]火星商店问题(线段树分治+可持久化01trie)
传送门 题意:序列上有nnn个商店,有两种事件会发生: sss商店上进购标价为vvv的一个物品 求编号为[l,r][l,r][l,r]之间的位置买ddd天内新进购的所有物品与一个数xxx异或值的最大值 ...
随机推荐
- ZBrush破解版下载,ZBrush中文版下载
11月11日这个令人兴奋的日子又来了.没错,“双十一”所有网购达人狂欢的日子.但是ZBrush却让心心念念的小伙伴们失望了一把,本以为双十一期间会有相关活动的,结果,官方并未提及,事实上,ZBrush ...
- 路飞学城Python-Day49
55-善于使用父亲的padding,而不是margin 56-文本属性和字体属性 div{ width: 300px; height: 100px; border: 1px solid red; /* ...
- 获取浏览器端的cookie方法
代码如下: function getCookie(key){ var cookies=document.cookie; if(cookies.length>0){ var start=cooki ...
- UVALive-7197 Axles 动态规划 多个背包问题
题目链接:https://cn.vjudge.net/problem/UVALive-7197 题意 需要生产n种(2<=n<=14)零件,每种零件可以用两种材料制作,对这两种材料的消耗相 ...
- 【bzoj 1502】月下柠檬树
月下柠檬树 题意 求n个圆与他们的公切线的定积分. 解法 求出圆的公切线就可以了. 特别坑的一点 : 最两端的圆,有可能会被其他的圆所包含,所以要重新求一下最左端与最右端. 比较坑的一点 : 精度要设 ...
- u-boot启动代码start.S详解
(1)定义入口.由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本 ...
- Vue框架Element UI教程-axios请求数据
Element UI手册:https://cloud.tencent.com/developer/doc/1270 中文文档:http://element-cn.eleme.io/#/zh-CN gi ...
- Jenkins学习总结(5)——免费DevOps开源工具简介
一:开发工具 1.版本控制系统 Git Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理. 2.代码托管平台 GitLab GitLab是一个利用Ruby on ...
- JavaScript push(),join() 函数
定义和用法 push方法 可向数组的末尾添加一个或多个元素,并返回一个新的长度. join方法 用于把数组中所有元素添加到一个指定的字符串,元素是通过指定的分隔符进行分割的. 语法 arrayObje ...
- ZOJ 3329
方程很明显有 d[i]=sum(pk*d[i+k])+p0*d[0]; 其中pi可以在开始时枚举求出. 设d[i]=A[i]*d[0]+B[i], 代入上式 d[i]=(sum(pk*A[i+k])+ ...