题目大意

给出数列 \(\text a\),询问区间 \([l,r]\) 内,满足 \(l\le i \le j\le r\) 的 \(i,j\) 使 \(a_i xor a_{i+1} xor...xor a_j\) 值最大,求这个最值

题解

这题比较新鲜,知道了一些从未知道的套路

先考虑 \(O(n^2 \log V)\) 的做法

显然对于询问 \([l,r]\) 扫一遍,用 \(Trie\) 经典地贪心求最大值即可

然后发现我们可以把扫一遍的 \(O(n)\) 级别的复杂度弄掉

就是考虑分块

求出从第 \(i\) 块第一个位置为起点到第 \(j\) 个位置的答案

可以 \(O(n\sqrt n \log V)\) 预处理出

然后查询直接查预处理的数组就可以跳过块,暴力求散的答案即可

\(Code\)

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std; const int N = 20005;
int n, q, t, size, a[N], sm[N], sum[64 * N], tr[32 * N][2], rt[N]; inline void update(int u , int v , int x)
{
for(register int i = 30; i >= 0; i--)
{
int c = (x >> i) & 1;
sum[v] = sum[u] + 1;
tr[v][c] = ++size;
tr[v][c ^ 1] = tr[u][c ^ 1];
v = tr[v][c] , u = tr[u][c];
}
sum[v] = sum[u] + 1;
} inline int query(int u , int v , int x)
{
int res = 0;
for(register int i = 30; i >= 0; i--)
{
int c = (x >> i) & 1 , k = sum[tr[v][c ^ 1]] - sum[tr[u][c ^ 1]];
if (k) res += (1 << i) , u = tr[u][c ^ 1] , v = tr[v][c ^ 1];
else u = tr[u][c] , v = tr[v][c];
}
return res;
} int st[N], ed[N], bl[N], g[155][N];
void Square()
{
int num = sqrt(n);
for(register int i = 1; i <= num; i++) st[i] = n / num * (i - 1) + 1, ed[i] = n / num * i;
ed[num] = n;
for(register int i = 1; i <= num; i++)
for(register int j = st[i]; j <= ed[i]; j++) bl[j] = i;
for(register int i = 1; i <= num; i++)
for(register int j = st[i]; j <= n; j++) g[i][j] = max(g[i][j - 1], query(rt[max(st[i] - 2, 0)], rt[j], sm[j]));
} int main()
{
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
scanf("%d%d%d", &n, &q, &t);
for(register int i = 1; i <= n; i++) scanf("%d", &a[i]), sm[i] = sm[i - 1] ^ a[i];
update(0, rt[0] = ++size, 0);
for(register int i = 1; i <= n; i++) update(rt[i - 1] , rt[i] = ++size , sm[i]);
Square();
for(int l, r, ans = 0; q; --q)
{
scanf("%d%d", &l, &r);
l = (l + t * ans) % n + 1, r = (r + t * ans) % n + 1;
if (l > r) swap(l, r);
ans = 0;
int x = bl[l], y = bl[r];
if (x == y) for(register int i = l - 1; i <= r; i++) ans = max(ans, query(rt[max(l - 2, 0)], rt[r], sm[i]));
else{
ans = g[x + 1][r];
for(register int i = l - 1; i <= ed[x]; i++) ans = max(ans, query(rt[max(l - 2, 0)], rt[r], sm[i]));
for(register int i = st[y]; i <= r; i++) ans = max(ans, query(rt[max(l - 2, 0)], rt[r], sm[i]));
}
printf("%d\n", ans);
}
}

JZOJ 5382. 数列的更多相关文章

  1. 【Luogu P2201】【JZOJ 3922】数列编辑器

    题面: Description 小Z是一个爱好数学的小学生.最近,他在研究一些关于整数数列的性质. 为了方便他的研究,小Z希望实现一个叫做"Open Continuous Lines Pro ...

  2. JZOJ 5922. sequence

    5922. [NOIP2018模拟10.23]sequence (File IO): input:sequence.in output:sequence.out Time Limits: 1000 m ...

  3. [JZOJ 5910] [NOIP2018模拟10.18] DuLiu 解题报告 (并查集+思维)

    题目链接: https://jzoj.net/senior/#contest/show/2530/0 题目: LF是毒瘤出题人中AK IOI2019,不屑于参加NOI的唯一的人.他对人说话,总是满口垃 ...

  4. 题解【CJOJ2608】[JZOJ 100043]第k小数

    P2608 - [JZOJ 100043]第k小数 Description 有两个非负整数数列,元素个数分别为N和M.从两个数列中分别任取一个数相乘,这样一共可以得到N*M个数,询问这N*M个数中第K ...

  5. C#求斐波那契数列第30项的值(递归和非递归)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. BZOJ1500[NOI2005]维修数列

    Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一 ...

  7. PAT 1049. 数列的片段和(20)

    给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段.例如,给定数列{0.1, 0.2, 0.3, 0.4},我们有(0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1 ...

  8. 斐波拉契数列加强版——时间复杂度O(1),空间复杂度O(1)

    对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - ) + F(n - ),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围 ...

  9. fibonacci数列(五种)

    自己没动脑子,大部分内容转自:http://www.jb51.net/article/37286.htm 斐波拉契数列,看起来好像谁都会写,不过它写的方式却有好多种,不管用不用的上,先留下来再说. 1 ...

  10. js中的斐波那契数列法

    //斐波那契数列:1,2,3,5,8,13…… //从第3个起的第n个等于前两个之和 //解法1: var n1 = 1,n2 = 2; for(var i=3;i<101;i++){ var ...

随机推荐

  1. 【Java SE】Day10接口、多态

    一.接口 1.概述 是一种引用类型,是方法的集合,内部封装了各种方法 引用类型:数组.类.接口.包装类 2.方法的定义格式 抽象方法:无方法体,子类实现 默认方法: 静态方法:static修饰,可以由 ...

  2. Ubuntu 22.04 搭建K8s集群

    目录 1. 虚拟机基础配置 配置静态ip 设置主机名 设置hosts 安装ssh 2. Ubuntu系统设置 禁用swap 修改内核参数 3. 安装containerd 4. 安装Kubernetes ...

  3. 互斥锁 线程理论 GIL全局解释器锁 死锁现象 信号量 event事件 进程池与线程池 协程实现并发

    目录 互斥锁 multiprocessing Lock类 锁的种类 线程理论 进程和线程对比 开线程的两种方式(类似进程) 方式1 使用Thread()创建线程对象 方式2 重写Thread类run方 ...

  4. 零基础入门 Java 后端开发,有哪些值得看的视频?

    目前网络上充满了大量的 Java 视频教程,然而内容却鱼龙混杂,为了防止小伙伴们踩坑,一枫结合自己的学习经验,向大家推荐一些不错的学习资源. 作为一名非科班转码选手,可以说,我是在哔哩哔哩上的研究生! ...

  5. Linux基础第五章 进程控制

    5.2 fork fork函数实现进程复制,类似于动物界的单性繁殖,fork函数直接创建一个子进程.这是Linux创建进程最常用的方法.在这一小节中,子进程概念指fork产生的进程,父进程指主动调用f ...

  6. c语言学习总结(原创)

    什么是标识符? 标识符是用来标识变量.函数.类.模块,或者任何其他用户自定义项目的名称,用它来命名程序正文中的一些实体,比如函数名.变量名.类名.对象名等.如:int a1=0; const b1=& ...

  7. [编程基础] C++多线程入门10-packaged_task示例

    原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 文章目录 10 pa ...

  8. 动力节点——day03

    接收键盘的输入:1.创建一个键盘扫描器对象 java.util.Scanner s=new Scanner(System.in); 2.接收用户输入s.nextInt(); 静态变量在类加载的时候就分 ...

  9. 重磅!瞄准 Web 3.0,谷歌云推出专为区块链服务的 Blockchain Node Engine!

    [本文由Cloud Ace整理发布,谷歌云服务请访问Cloud Ace 官网] 区块链技术正在为世界各地的消费者和企业带来巨大的创新和价值创造.随着技术变得越来越主流,公司需要可扩展.安全和可持续的基 ...

  10. golang主协程等待子协程执行完毕

    无限等待 计时等待 channel通信 select 等待组