http://www.lydsy.com/JudgeOnline/problem.php?id=2741

分块或可持久化trie

可以先看看这个:高斯消元解XOR方程组

分块做法:

我们先求出前i个数的异或和,即b[i]=a[1]^a[2]^...^a[i],不失一般性,记b[0]=0。

那么a[i]^a[i+1]^...^a[j-1]^a[j]=b[j]^b[i-1]。

所以原问题变成在b[l-1...r]中任选2个数,使得异或和最大。

我们将0..N分成$\sqrt{N}$块,不妨记第i块的左端为l[i],右端为r[i]。

每个块建一棵二进制树,将所有的数插入到所在的块的二进制树中。

然后记$f[i][j]$表示b[i]与第j块中某一个数异或(即b[i]与b[l[j]...r[j]]中的某一个数异或),得到的最大的异或和是多少。这个可以在$O(31N\sqrt{N})$的时间内解决。

$g[i][j]$表表示第i块中某一个数与第j块中某一个数异或(即b[l[i]...r[i]]中的某一个数异或与b[l[j]...r[j]]中的某一个数异或),得到的最大的异或和是多少。这个可以在$O(N\sqrt{N})$从F数组得到。

现在预处理已经完成了。

对于询问区间[l-1...r],分类讨论一下就可以了,时间复杂度是$O(MN)$

所以总的时间复杂度是$O(31N\sqrt{N}+MN)$

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b) for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define p_b(a) push_back(a)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=;
const int maxcnt=; struct Tnode
{
Tnode *son[];
inline Tnode(){son[]=son[]=;}
}; int N,Q;
int len,cnt,id[maxN+],l[maxcnt+],r[maxcnt+];
int a[maxN+];
Tnode *rt[maxcnt+];
int f[maxN+][maxcnt+];
int g[maxcnt+][maxcnt+];
int lastans; int t[];
inline void insert(Tnode *p,int v)
{
int i;
re(i,,)t[i]=v&,v>>=;
red(i,,)
{
if(!p->son[t[i]])p->son[t[i]]=new Tnode;
p=p->son[t[i]];
}
}
inline int find(Tnode *p,int v)
{
int i,res=;
re(i,,)t[i]=v&,v>>=;
red(i,,)
{
int to=(p->son[t[i]^])?t[i]^:t[i];
res=(res<<)+to;
p=p->son[to];
}
return res;
} int main()
{
freopen("bzoj2741.in","r",stdin);
freopen("bzoj2741.out","w",stdout);
int i,j;
N=gint()+;Q=gint();
re(i,,N)a[i]=gint();
re(i,,N)a[i]^=a[i-];
len=int(sqrt(DB(N)));
re(i,,N)
{
if((i-)%len==)r[cnt]=i-,l[++cnt]=i;
id[i]=cnt;
}
r[cnt]=N;
re(i,,cnt)rt[i]=new Tnode;
re(i,,N)insert(rt[id[i]],a[i]);
re(i,,N)re(j,,cnt)f[i][j]=a[i]^find(rt[j],a[i]);
re(i,,N)re(j,,cnt)upmax(g[id[i]][j],f[i][j]);
lastans=;
while(Q--)
{
int x=gint(),y=gint();
int L=int( min( (LL(x)+LL(lastans))%LL(N-)+ , (LL(y)+LL(lastans))%LL(N-)+ ) ) + ;
int R=int( max( (LL(x)+LL(lastans))%LL(N-)+ , (LL(y)+LL(lastans))%LL(N-)+ ) ) + ;
L--;
lastans=;
if(id[L]==id[R] || id[L]+==id[R])
{
re(i,L,R)re(j,i,R)upmax(lastans,a[i]^a[j]);
}
else
{
int p=(L==l[id[L]])?id[L]:id[L]+,q=(R==r[id[R]])?id[R]:id[R]-;
re(i,p,q)re(j,i,q) upmax(lastans,g[i][j]);
re(i,L,l[p]-)re(j,p,q) upmax(lastans,f[i][j]);
re(i,r[q]+,R)re(j,p,q) upmax(lastans,f[i][j]);
re(i,L,l[p]-)re(j,r[q]+,R)upmax(lastans,a[i]^a[j]);
re(i,L,l[p]-)re(j,i+,l[p]-)upmax(lastans,a[i]^a[j]);
re(i,r[q]+,R)re(j,i+,R)upmax(lastans,a[i]^a[j]);
}
cout<<lastans<<endl;
}
return ;
}

可持久化trie做法:

可持久化trie的想法比较简单。

第i棵trie中插入了b[0...i],我们可以从第i-1棵trie得到。

对于询问区间[l-1...r],枚举其中一个数,然后同时在第r棵trie和第l-2棵trie中走即可。

总的时间复杂度是$O(31MN)$

bzoj2741【FOTILE模拟赛】L的更多相关文章

  1. BZOJ2741 FOTILE模拟赛L(分块+可持久化trie)

    显然做个前缀和之后变成询问区间内两个数异或最大值. 一种暴力做法是建好可持久化trie后直接枚举其中一个数查询,复杂度O(nmlogv). 观察到数据范围很微妙.考虑瞎分块. 设f[i][j]为第i个 ...

  2. BZOJ2741:[FOTILE模拟赛]L

    Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 .. ...

  3. 【BZOJ2741】【块状链表+可持久化trie】FOTILE模拟赛L

    Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 .. ...

  4. 【bzoj2741】[FOTILE模拟赛] L

    Portal --> bzoj2741 Solution 突然沉迷分块不能自拔 考虑用分块+可持久化trie来解决这个问题 对于每一块的块头\(L\),预处理\([L,i]\)区间内的所有子区间 ...

  5. 【bzoj2741】[FOTILE模拟赛]L 可持久化Trie树+分块

    题目描述 FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor A ...

  6. BZOJ.2741.[FOTILE模拟赛]L(分块 可持久化Trie)

    题目链接 首先记\(sum\)为前缀异或和,那么区间\(s[l,r]=sum[l-1]^{\wedge}sum[r]\).即一个区间异或和可以转为求两个数的异或和. 那么对\([l,r]\)的询问即求 ...

  7. bzoj 2741 [FOTILE模拟赛] L

    Description 多个询问l,r,求所有子区间异或和中最大是多少 强制在线 Solution 分块+可持久化trie 1.对于每块的左端点L,预处理出L到任意一个i,[L,j] 间所有子区间异或 ...

  8. 【BZOJ2741】【FOTILE模拟赛】L 分块+可持久化Trie树

    [BZOJ2741][FOTILE模拟赛]L Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max( ...

  9. BZOJ2741: 【FOTILE模拟赛】L

    2741: [FOTILE模拟赛]L Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1170  Solved: 303[Submit][Status] ...

  10. bzoj 2741: 【FOTILE模拟赛】L 分塊+可持久化trie

    2741: [FOTILE模拟赛]L Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1116  Solved: 292[Submit][Status] ...

随机推荐

  1. springMVC之本地化和国际化

    spring框架的大部分都支持国际化,就像springMVC一样.DispatcherServlet使你能够动态的通过客户端的本地语言进行配置.这是通过LocaleResolver完成的.   当一个 ...

  2. Android 布局 ViewGroup

    布局 res/layout 命名规则(全部小写) activity_ fragment_ item_ 基础组件 com.android.widget包下 父类View view:屏幕上一块矩阵区域 能 ...

  3. CComPtr用法

    COM接口指针很危险,因为使用过程中需要每一个使用者都要严格并且正确的AddRef和Release,一旦出现问题,就会造成对象不能被正常释放,或者对象被重复删除,造成程序崩溃.所以使用COM接口,必须 ...

  4. 读取Excel数据绑定到Gridview进行显示

    读取Excel数据绑定到Gridview进行显示示例代码. 读取excel代码 /// <summary> /// 读取Excel /// authon:codeo.cn /// < ...

  5. 递归---NYOJ-176 整数划分(二)和NYOJ-279队花的烦恼二

    这道题目的递归思想和第一个题差不多, 主要思想是:func(n, m)的作用是将n划分为m个. 1. 如果n < m 的时候肯定是不能划分的,所以就返回0 2. 如果m = 1 或者 n = m ...

  6. Blade和其他构建工具有什么不同

    大部分人都至少接触过不止一种构建工具,比如make,autotools.而我们开发了Blade,为什么那么多现成的工具不用,而又再造了一个轮子,相对于传统的make等工具,Blade的好处在又哪里呢? ...

  7. C# 面向对象 , 类与对象

    一,类的字段 类的字段, 就是类里面的 数据. 二,类的方法 1 , 函数的重载 , 如何判断:  是由两个或多个同名函数组成的,但是函数要有不同的参数.或个数.(参数  是函数的输入的东西) shu ...

  8. java 线程池用法

    public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, ...

  9. mongodb的oplog遇到的问题

    mongodb调整oplog的大小的方法 关闭当前服务器,将服务器以单机模式启动.这是一种方法,还有没有其他方法? mongodb实时扫描oplog,判断记录到哪个地方了 如果扫描oplog的程序挂掉 ...

  10. JavaScript 函数之 ------------------ 闭包

    谈到闭包,人们常常会把匿名函数和闭包混淆在一起.闭包是指由权访问另一个函数作用域中的变量的函数.创建闭包的常见方式,就是在一个函数内部创建另一个函数,仍以前面的 createComparisonFun ...