Description

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。

Input

第一行两个整数N和M。
第二行有N个正整数,其中第i个数为Ai,有多余空格。
后M行每行两个数x,y表示一对询问。
 
 

Output

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

Sample Input

3 3
1 4 3
0 1
0 1
4 3

Sample Output

5
7
7

HINT

HINT

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

Source

【分析】
第一次写可持久化trie,还有点问题。
题解网上都是...先不说了
 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map> const int N = + ;
const int SIZE = ;//块状链表的根号50000
const int M = + ;
using namespace std;
typedef long long ll;
struct Node{
int val;//代表数量
int num;//代表值
Node *ch[];
}mem[N * * ], *root[N];
int n, m;//n为数量,m为操作次数
struct BLOCK_LIST{//块状链表
int data[SIZE];
int size, next;
void init(){
size = ;
memset(data, , sizeof(data));
next = -;
}
}list[SIZE];
int tot = ;//记录mem使用空间
int Max[SIZE + ][SIZE + ], Pos;//表示从i到j块的最大异或值
int data[N]; Node *NEW(){//创建新trie节点
Node *p = &mem[tot++];
p->val = p->num = ;
p->ch[] = p->ch[] = NULL;
return p;
}
void insert(Node *&p, Node *&last, int x){//k为根
p = NEW(); Node *u = p, *a = last;
for (int i = ; i >= ; i--){
int t = ((( << i) & x) == ? : );
if (u->ch[t] == NULL){
u->ch[t] = NEW();
u->ch[t]->val = t;
u->ch[t]->num = a->ch[t]->num + ;
}
u->ch[t ^ ] = a -> ch[t ^ ];
u = u -> ch[t];
a = a -> ch[t];
}
return;
}
int find(Node *&a, Node *&b, int val){
int Ans = ;
Node *x = a, *y = b;
for (int i = ; i >= ; i--){ int t = (((( << i) & val) == ? : ) ^ );
if (x->ch[t] == NULL || (x->ch[t]->num - y->ch[t]->num) <= ) t = (t ^ );
Ans += ( << i) * t;
x = x->ch[t];
y = y->ch[t];
}
//Ans += t;
return Ans;
} void prepare(){
memset(Max, , sizeof( Max ));
Pos = ;//Pos为块状链表的标号
list[Pos++].init();
insert(root[], root[], );//插入可持久化trie
for (int cur = , i = ; i <= n; cur = list[cur].next){
int j, M = ;//M用来记录块的最大值
for (j = ; j < SIZE && i <= n; i++, j++){
list[cur].data[j] = data[i];
list[cur].size++;
insert(root[i + ], root[i], data[i]);//插入可持久化trie
int M2 = data[i];
//M2 = find(root[i + 1], root[cur * SIZE], list[cur].data[j]);
//printf("%d\n", M2);
//if (M2 == data[i]) M2 = 0;//显然如果是它自己不如不加即直接从开头一直异或到i
//Max[cur][cur] = M2;
for (int k = Pos - ; k >= ; k--){
int tmp = find(root[i + ], root[k * SIZE], data[i]);
//if (tmp == data[i]) tmp = 0;
if ((M2 ^ data[i]) < (tmp ^ data[i])) M2 = tmp;
Max[k][cur] = max(Max[k][cur], M2 ^ data[i]);//顺便利用O(sqrt(n))的时间预处理出Max数组
}
}
//创建新块
if (j == SIZE){
list[Pos].init();
list[cur].next = Pos++;
}
}
//printf("%d\n", root[1]->ch[0]->ch[1]->num);
}
int query(int l, int r){
int x = (l - ) / SIZE, y = (r - ) / SIZE;//x代表l和r所代表的块
int Ans = ;
if (x == y){
for (int i = l; i <= r; i++)
Ans = max(Ans, find(root[r + ], root[l - ], data[i]) ^ data[i]);
return Ans;
}else{
if (x <= y - ) Ans = Max[x ][y - ];
//for (int i = r; i >= l; i--) if ((data[i] ^ data[i - 1]) == 32767) printf("fuck");
for (int i = l; i <= ((x + ) * SIZE) && i <= n; i++) Ans = max(Ans, find(root[r + ], root[l - ], data[i]) ^ data[i]);
for (int i = r; i > y * SIZE; i--) Ans = max(Ans, find(root[r + ], root[l - ], data[i]) ^ data[i]);
return Ans;
//for (int i = l; i <= r; i++)
// Ans = max(Ans, find(root[r + 1], root[l - 1], data[i]) ^ data[i]);
//return Ans;
}
}
//处理询问
void work(){
int last_ans = ;
for (int i = ; i <= m; i++){
int x, y, l, r;
scanf("%d%d", &l, &r);
//l--;
//l = min(((ll)((ll)x + (ll)last_ans) % n) + 1 , ((ll)((ll)y + (ll)last_ans) % n)+ 1);
//r = max(((ll)((ll)x + (ll)last_ans) % n) + 1 , ((ll)((ll)y + (ll)last_ans) % n)+ 1);
last_ans = query(l, r);
printf("%d\n", last_ans);
}
}
//单纯的插入一个数
void build(Node *&b, int x){
Node *u = b;
for (int i = ; i >= ; i--){
int t = ((( << i) & x) == ? : );//表示这一位是否是0
if (u->ch[t] == NULL){
u->ch[t] = NEW();
u->ch[t]->val = t;
u->ch[t]->num = ;//注意,这里仅仅只是建树,所以不能改数字
}
u = u->ch[t];
}
return;
}
void init(){
//读入+建初始树
scanf("%d%d", &n, &m);
for (int i = ; i < N; i++) root[i] = NULL;
root[] = NEW();
data[] = ;
for (int i = ; i <= n; i++){
scanf("%d", &data[i]);
data[i] = data[i] ^ data[i - ];
build(root[], data[i]);
//printf("%d\n", data[i]);
}
build(root[], );//记得加0
//printf("%d", root[0]->val);
}
void debug(){
insert(root[], root[], );
insert(root[], root[], );
insert(root[], root[], );
printf("%d\n", find(root[], root[], ));
} int main(){
#ifdef LOCAL
freopen("data.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
init();
prepare();
work();
printf("%d\n", tot);
//debug();
return ;
}

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

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

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

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

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

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

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

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

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

  5. bzoj 2741 [FOTILE模拟赛] L

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

  6. BZOJ2741:[FOTILE模拟赛]L

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

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

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

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

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

  9. BZOJ2741: 【FOTILE模拟赛】L

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

随机推荐

  1. IIS7 上传 下载文件大小限制的设置

    IIS7 上传 下载文件大小限制的设置 本文来自IISBOY网 一.找到修改大小的配置文件和配置节点 本文来自IISBOY网 打开你系统盘(我是C盘),找到 C:\Windows\System32\i ...

  2. SWMM[Storm Water Management Model]模型代码编译调试环境设置

    1. 下载计算引擎源代码后解压, 目前最新版本5-0-022. 其中包含源文件和工程文件,选择vc2005_con.在源代码目录下创建VC2005_CON目录拷贝VC2005-CON.VCPROJ 放 ...

  3. SQL数据类型介绍

    在计算机中数据有两种特征:类型和长度.所谓数据类型就是以数据的表现方式和存储方式来划分的数据的种类.    在SQL Server 中每个变量.参数.表达式等都有数据类型.系统提供的数据类型分为几大类 ...

  4. UML 的基本组成

    UML 是由UML构造块.规则.通用机制三部分组成的.而UML构造块由建模元素(事物).关系和图组成. 建模元素 建模元素是对模型中最具有代表性的成分的抽象.一般情况下,将建模元素分为结构元素.行为元 ...

  5. 二进制文件和ASCII文件有何差别

    二进制文件和ASCII文件(即文本文件)的差别,对于和计算机亲近时间尚短的同学是个难题.本文用简单的样例,试图展示当中的道道,希望能对菜鸟们有些帮助. 1.一个样例:两种100000 有程序: #in ...

  6. 最新Connectify注冊码(序列号) Connectify3.7序列号 破解版

    Connectify序列号.最新注冊码 今天给大家公布一个Connectify最新版的序列号(注冊码) 今天给大家公布一个Connectify最新版的序列号(注冊码) 经本人測试该注冊码为最新版Con ...

  7. 他们都没告诉你适配 Android N 需要注意什么

    还记得 6.0 对 Apache Http 库的废除导致的应用崩溃吗?还记得 6.0 中 MAC id 始终返回为空导致的唯一 id 混合生成算法大幅失效吗? 1. Android 中 Java 的实 ...

  8. 文档对象模型操作xml文档

    简介 :文档对象模型(DOM)是一种用于处理xml文档的API函数集. 2.1文档对象模型概述 按照W3C的定义,DOM是“一种允许程序或脚本动态地访问更新文档内容,结构和样式的.独立于平台和语言的规 ...

  9. KineticJS教程(1-2)

    1.基本结构 KineticJS首先是要绑定到HTML页面上的一个DOM容器元素上,比如最常用的<div>标签.KineticJS在此容器中创建一个称之为舞台(stage)的结构,这个舞台 ...

  10. gulp的点点滴滴

    去年用gulp,但一直没有写篇博客,今天有时间无聊写一篇.... 什么是gulp?gulp的官网title上对这个工具有一个比较准确的定义,叫做:基于流的自动化构建工具.如果你查看它的网页源代码,还会 ...