题目

FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和。

即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r。

为了体现在线操作,对于一个询问(x,y):

l = min ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).

r = max ( ((x+lastans) mod N)+1 , ((y+lastans) mod N)+1 ).

其中lastans是上次询问的答案,一开始为0。

输入格式

第一行两个整数N和M。

第二行有N个正整数,其中第i个数为Ai,有多余空格。

后M行每行两个数x,y表示一对询问。

输出格式

共M行,第i行一个正整数表示第i个询问的结果。

输入样例

3 3

1 4 3

0 1

0 1

4 3

输出样例

5

7

7

提示

HINT

N=12000,M=6000,x,y,Ai在signed longint范围内。

题解

区间异或和最大,转化为两个前缀和

多次询问不同区间,用可持久化trie树

但每次要任意选出两个数,而常规的trie树只支持一个数询问区间和它的最大异或值,不能处理区间内任意两个数异或和最大值

何破?

我们不可能每次询问\(O(n^2logn)\)枚举其中一个数

那就预处理!

如果我们能预处理出每个区间异或最大值,就是\(O(n^2logn)\)预处理,\(O(1)\)查询

能不能均摊一下?

分块!

我们只预处理每个块头到其后面所有位置的数异或的最大值

具体的,设\(f[i][j]\)表示\(i\)块开头位置到\(j\)中所有数异或的最大值,记块头为\(u\),则\(f[i][j]\)即为区间\([u,j]\)的答案

算出\(f[i][j]\)只需要枚举每个\(j\)就可以了

具体地,\(f[i][j] = max(f[i][j - 1],query(j,区间[u,j - 1]))\)

那么每次询问的时候,对于\(l\)之后的第一个块头\(u\),可以得到出后面的答案\(f[u][r]\)

所以我们只需要计算区间\([l,u - 1]\)的数与其后面的数的最大异或值

这个区间大小不会超过\(\sqrt{n}\),所以可以直接统计

总的复杂度\(O(n\sqrt{n}logn)\)

【坑点,给出的x,y可能超过int范围】

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define LL long long int
using namespace std;
const int maxn = 12005,Bit = 31,maxm = 6000000,INF = 100000000;
inline LL read(){
LL out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
LL n,m,A[maxn],sum[maxn],bin[40];
LL f[200][maxn],block[maxn],B,lans;
struct trie{
int ch[maxm][2],sum[maxm],rt[maxn],cnt;
int ins(int pre,int x){
int tmp,u;
tmp = u = ++cnt;
for (int i = Bit; i >= 0; i--){
ch[u][0] = ch[pre][0];
ch[u][1] = ch[pre][1];
sum[u] = sum[pre] + 1;
LL t = x & bin[i]; t >>= i;
pre = ch[pre][t];
u = ch[u][t] = ++cnt;
}
sum[u] = sum[pre] + 1;
return tmp;
}
LL query(int u,int v,int x,int dep){
if (dep < 0) return 0;
LL t = x & bin[dep]; t >>= dep;
if (sum[ch[u][t ^ 1]] - sum[ch[v][t ^ 1]])
return bin[dep] + query(ch[u][t ^ 1],ch[v][t ^ 1],x,dep - 1);
return query(ch[u][t],ch[v][t],x,dep - 1);
}
}T;
int main(){
bin[0] = 1; for (int i = 1; i <= Bit; i++) bin[i] = bin[i - 1] << 1;
n = read(); m = read(); B = (int)sqrt(n) + 1;
n++;
for (int i = 2; i <= n; i++) A[i] = read();
for (int i = 1; i <= n; i++){
sum[i] = sum[i - 1] ^ A[i];
T.rt[i] = T.ins(T.rt[i - 1],sum[i]);
block[i] = i / B;
}
for (int i = 1; i <= n; i++){
if (i == 1 || block[i] != block[i - 1]){
int b = block[i];
for (int j = i; j <= n; j++){
f[b][j] = max(f[b][j - 1],T.query(T.rt[j - 1],T.rt[i - 1],sum[j],Bit));
}
}
}
n--;
LL l,r,x,y;
while (m--){
x = read(); y = read();
l = min (((x + lans) % n) + 1, ((y + lans) % n) + 1);
r = max (((x + lans) % n) + 1, ((y + lans) % n) + 1) + 1;
lans = 0;
if (block[l] != block[r]) lans = f[block[l] + 1][r];
for (int i = l; block[i] == block[l] && i < r; i++){
lans = max(lans,T.query(T.rt[r],T.rt[i],sum[i],Bit));
}
printf("%lld\n",lans);
}
return 0;
}

BZOJ2741 【FOTILE模拟赛】L 【可持久化trie + 分块】的更多相关文章

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

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

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

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

  3. BZOJ2741:[FOTILE模拟赛]L

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

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

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

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

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

  6. BZOJ 2741: 【FOTILE模拟赛】L(可持久化Trie+分块)

    传送门 解题思路 首先求出前缀异或和,那么问题就转化成了区间内选两个数使得其异或和最大.数据范围不是很大考虑分块,设\(f[x][i]\)表示第\(x\)块开头到\(i\)这个位置与\(a[i]\)异 ...

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

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

  8. bzoj 2741 [FOTILE模拟赛] L

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

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

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

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

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

随机推荐

  1. 交互干货必收 | App界面交互设计规范

    原文地址:http://www.woshipm.com/ucd/193776.html

  2. ucosii(2.89)mbox 应用要点

    OSMboxCreate(void *msg)     当创建一个mbox时候,消息邮箱允许(任务或者中断)向其他一个或者几个任务发送消息.初始化msg指向消息邮箱中的消息. void*OSMboxP ...

  3. Robot Framework(十一) 执行测试用例——后处理输出

    3.3后处理输出 在测试执行期间生成的XML输出文件可以在之后由rebot工具进行后处理,该工具是Robot Framework的组成部分.在测试执行期间生成测试报告和日志时会自动使用它,但在执行后也 ...

  4. minGw64编译Qt时遇到too many sections问题

    minGw64编译Qt时遇到too many sections问题: 修改\Src\qtbase\mkspecs\win32-g++\qmake.conf中 QMAKE_CFLAGS         ...

  5. RN笔记

    https://facebook.github.io/react-native/docs/using-a-listview.html react native类似于react,不过它使用的是原生组件, ...

  6. CSS 布局经典问题初步整理

    CSS 定位问题 主要就是经典的绝对定位,相对定位问题. 10个文档学布局:通过十个例子讲解布局,主要涉及相对布局,绝对布局,浮动. 百度前端学院笔记 – 理解绝对定位:文章本身一般,几篇参考文献比较 ...

  7. LeetCode(8)String to Integer (atoi)

    题目: Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input ca ...

  8. this version of SLF4J requires log4j version 1.2.12 or later.

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFacto ...

  9. Android开发工具——Gradle知识汇总

    1.什么是构建工具 Eclipse大家都知道是一种IDE(集成开发环境),最初是用来做Java开发的,而Android是基于Java语言的,所以最初Google还是希望Android能在Eclipse ...

  10. struts 乱码

    在进行struts开发的过程中,总也是出现很多的乱码问题 ,但归根到底,也只是以下三种情况: ㈠页面显示中文乱码 ㈡传递参数中文乱码 ㈢国际化资源文件乱码 下面就这三中情况介绍怎么在具体项目中处理这些 ...