题意:给定一个长度为n的序列,m次询问,每次询问一个区间[l, r],求max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r。(n<=12000, m<=6000, Ai在signed longint范围内)

#include <bits/stdc++.h>
using namespace std; const int nT=5000005, N=12005;
struct node *null;
struct node {
node *c[2];
int s;
}pool[nT], *it=pool;
node *newT() { node *x; x=it++; x->c[0]=x->c[1]=null; x->s=0; return x; }
node *add(node *p, int y, int dep=30) {
node *x=newT();
if(dep==-1) return x;
*x=*p;
int f=(y>>dep)&1;
x->c[f]=add(p->c[f], y, dep-1); ++x->c[f]->s;
return x;
}
int query(node *a, node *b, int k, int dep=30) {
if(dep==-1) return 0;
int f=(k>>dep)&1, ff=f^1;
if(b->c[ff]->s>a->c[ff]->s) return (1<<dep)|query(a->c[ff], b->c[ff], k, dep-1);
return query(a->c[f], b->c[f], k, dep-1);
}
node *Root[N], **root=Root+1;
int a[N], n, m, size, num, pos[N], d[120][N], last; void init() {
null=new node; null->c[0]=null->c[1]=null; null->s=0;
root[0]=null;
root[-1]=null; scanf("%d%d", &n, &m); //++n;
for(int i=1; i<=n; ++i) scanf("%d", &a[i]), a[i]^=a[i-1];
for(int i=1; i<=n; ++i) root[i]=add(root[i-1], a[i]);
size=sqrt(n+0.5);
num=(n-1)/size+1;
for(int i=1; i<=n; ++i) pos[i]=(i-1)/size+1;
for(int i=1; i<=num; ++i) {
int pi=(i-1)*size+1;
for(int j=pi; j<=n; ++j) d[i][j]=max(d[i][j-1], query(root[pi-1], root[j], a[j]));
}
}
int getans(int l, int r) {
--l;
int bl=pos[l], ret=0;
if(pos[r]>bl) ret=d[bl+1][r];
for(int i=l, end=min(r, bl*size); i<=end; ++i) ret=max(ret, query(root[l-1], root[r], a[i]));
return ret;
}
void solve() {
int x, y, l, r;
while(m--) {
scanf("%d%d", &x, &y);
x=(((long long)last+x)%n)+1;
y=(((long long)last+y)%n)+1;
l=min(x, y); r=max(x, y); //printf("%d %d\n", l, r);
printf("%d\n", last=getans(l, r));
}
}
int main() {
init();
solve();
return 0;
}

  

(自己的傻×做法,线段树套可持久化trie,mle成翔)

#include <bits/stdc++.h>
using namespace std; typedef long long ll;
const int M=8000005;
struct node *null;
struct node {
node *l, *r;
int cnt;
}pool[M], *bin[M], *it=pool, *nod;
int top;
node *newnode() {
node *x;
if(!top) { if(pool+M==it) exit(0); x=it++; }
else x=bin[--top];
x->l=x->r=null; x->cnt=1;
return x;
}
void clean(node *&x) {
if(x!=null && x!=nod && !(--x->cnt)) { bin[top++]=x; clean(x->l); clean(x->r); }
x=null;
}
node *merge(node *a, node *b) {
if(a==null) { ++b->cnt; return b; }
if(b==null) { ++a->cnt; return a; }
node *x=newnode();
x->l=merge(a->l, b->l);
x->r=merge(a->r, b->r);
return x;
}
node *add(node *p, ll y, int dep) {
if(dep==-1) return nod;
node *x=newnode();
x->l=p->l;
x->r=p->r;
if((y>>dep)&1) ++x->l->cnt, x->r=add(p->r, y, dep-1);
else ++x->r->cnt, x->l=add(p->l, y, dep-1);
return x;
}
node *add(node *p, ll y) { node *x=add(p, y, 63); clean(p); return x; }
node *build(node *a, node *b) {
if(a==null || b==null) return null;
node *x=newnode();
if(b->l!=null) {
x->l=build(a->l, b->l);
x->r=build(a->r, b->l);
}
if(b->r!=null) {
node *t;
x->l=merge(t=x->l, build(a->r, b->r)); clean(t);
x->r=merge(t=x->r, build(a->l, b->r)); clean(t);
}
return x;
}
void P(node *x, ll now, int dep=63) {
if(x==null) return;
if(dep==-1) printf("now:%lld\n", now);
P(x->l, now, dep-1);
P(x->r, now|(1<<dep), dep-1);
}
void D(node *x) {
P(x, 0); puts("");
} struct T {
node *l, *r, *all;
ll sum;
void pushup(T &lc, T &rc) {
sum=lc.sum^rc.sum;
static node *t;
l=merge(lc.l, build(rc.l, add(null, lc.sum)));
r=merge(rc.r, build(lc.r, add(null, rc.sum)));
all=merge(lc.all, rc.all); // printf("top:%d\n", top);
all=merge(t=all, build(lc.r, rc.l)); clean(t); // printf("sum:%lld , have:\n", sum); D(all);
}
ll get(node *x, int dep, bool flag) {
if(dep==-1) return 0;
ll ret=0;
if(x->l!=null && x->r!=null)
if(flag) ret=get(x->l, dep-1, 0);
else ret=(1ll<<dep), ret|=get(x->r, dep-1, 0);
else if(x->l==null && x->r!=null)
ret=(1ll<<dep), ret|=get(x->r, dep-1, 0);
else if(x->r==null && x->l!=null)
ret=get(x->l, dep-1, 0);
else puts("error");
return ret;
}
ll get() { return get(all, 63, 1); }
void clr() { clean(l); clean(r); clean(all); }
T& operator=(const T &a) { l=a.l; r=a.r; all=a.r; sum=a.sum; ++l->cnt; ++r->cnt; ++all->cnt; return *this; }
}t[12005<<2]; int n, q;
ll a[12005];
void build(int l, int r, int x) {
if(l==r) {
t[x].l=t[x].r=t[x].all=add(null, a[l]); // printf("%lld\n", a[l]); D(t[x].all);
t[x].sum=a[l];
return;
}
int mid=(l+r)>>1, lc=x<<1, rc=lc|1;
build(l, mid, lc);
build(mid+1, r, rc);
t[x].pushup(t[lc], t[rc]);
}
void query(int l, int r, int x, int L, int R, T &ret) {
if(L<=l && r<=R) { ret=t[x]; return; }
int mid=(l+r)>>1;
if(R<=mid) { query(l, mid, x<<1, L, R, ret); return; }
else if(mid<L) { query(mid+1, r, x<<1|1, L, R, ret); return; }
T lc, rc;
query(l, mid, x<<1, L, R, lc);
query(mid+1, r, x<<1|1, L, R, rc);
ret.pushup(lc, rc); lc.clr(); rc.clr();
}
void init() {
null=new node; null->l=null->r=null; null->cnt=1;
nod=newnode();
}
int main() {
scanf("%d%d", &n, &q);
init();
for(int i=1; i<=n; ++i) scanf("%lld", &a[i]);
build(1, n, 1);
int last=0, x, y, l, r;
T t;
while(q--) {
scanf("%d%d", &x, &y);
x=((x+last)%n)+1;
y=((y+last)%n)+1;
l=min(x, y);
r=max(x, y); // printf("l:%d, r:%d\n", l, r);
query(1, n, 1, l, r, t);
printf("%d\n", last=t.get());
t.clr();
}
return 0;
}

  

题解:

我看到大家的tag是可持久化trie后..我就往这个方向思考了下...就yy出了第一种sb做法.......................

即:发现我们只需要维护二进制位...然后查询就是在对应区间一直向右走即可(特判符号位...),用线段树维护区间........可持久化合并trie.......可是你会发现.........有O(nlogn)次合并..每次合并O(size(trie)).................然后可能又tle又mle。反正我开了引用计数的垃圾回收也跪了...............玛雅,rewrite的节奏啊...3k啊.............然后查题解..................发现是分块= =....什么鬼................

吐槽:最近到底怎么了.....................越是放假就越颓废??我感觉一放假,什么事情都会发生= =...这几天天天家里来客人妈呀...........能不能愉快的做题了........而且由于脑袋不知怎么得..转的特别慢...脑洞到是还好..可是一些简单的东西我要想好久啊啊>_<。。。还有本题竟然没有负数.....而且在int范围内............

ydc狂D蒟蒻我TAT....我已经被D成狗了.........ydc(先发了我这篇还没写完的博文....又发了一个自己讲莫队分块的博文的链接...下边是有我20天前的脑残留言的):“我怎么感到是在羞辱我”...............................(妈呀...还是在半群里...

真正的题解:

首先转化问题(妈呀完全没想到啊...),由于xor操作有特殊的性质,即$a \otimes b \otimes b = a$所以我们要求一段区间[a,b]的xor和,可以由[0, b]和[0, a-1]的xor值得来,设$s[i]=a[1] \otimes a[2] \otimes \cdots \otimes a[i]$,那么[l, r]区间的xor和就是 $s[r] \otimes s[l-1]$

果然我是脑残吗...

然后考虑区间最大的....即我们要求区间$[l, r]$最大的xor值,就是要求

$$max\{ s[j-1] \otimes s[i], l<=j<=i<=r \}$$

转化一下,其实就是要求$[l-1, r]$这个区间取两个数$i, j$求最大的$s[j] \otimes s[i]$(可以直接忽略i=j的情况,对结果无影响...)

容易得到dp方程,设d[i, j]表示区间$[i, j]$取两个数最大的xor值

$$d[i,j]=max\{d[i,j-1], f(s[j], \{s[l-1 \cdots r] \} ) \}, f表示将s[j]放到那个集合中找到一个最大的xor和\}$$

而这个方程外层都已经是$O(n^2)$的...

先考虑决策....容易想到这是个类似trie的东西....然后自己就能yy出来可持久化trie了...trie的边就代表一个二进制位..然后从上往下走即可....请自行yy...(....可持久化用在两个地方...1、省内存...2、区间信息...

然后就是分块大法!

引用ydc:“一般莫队能做的,分块+可持久化线段树/可持久化块状链表都是能做的”,orz

我们分块处理上边的方程..先分成$\sqrt n$块..然后方程$d[i,j]$表示第$i$块的起点到第$j$个元素的最大异或值...方程转移一样...这样预处理就是$O(31*n^{1.5})$了...(31是位数别说你看不懂..即log(2^31)

然后对于连续的我们直接得到答案,最后在处理一下非连续的即可...

总复杂度

$O(31*n^{1.5})$预处理,$O(31*mn^{0.5})$查询...可以水过..

【BZOJ】2741: 【FOTILE模拟赛】L的更多相关文章

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

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

  2. bzoj 2741 [FOTILE模拟赛] L

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

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

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

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

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

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

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

  6. BZOJ2741:[FOTILE模拟赛]L

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

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

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

  8. 【BZOJ】【2741】【FOTILE模拟赛】L

    可持久化Trie+分块 神题……Orz zyf & lyd 首先我们先将整个序列搞个前缀异或和,那么某一段的异或和,就变成了两个数的异或和,所以我们就将询问[某个区间中最大的区间异或和]改变成 ...

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

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

  10. BZOJ2741: 【FOTILE模拟赛】L

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

随机推荐

  1. 攻城狮在路上(肆)How tomcat works(二) 一个简单的servlet容器

    该节在上一节的基础上增加了所谓对静态资源和动态资源访问的不同控制流程.示例里面采用的是对路径“/servlet/”进行了特殊处理. 一. 主要还是从HttpServer1中的main方法开始,先解析出 ...

  2. 在VS 2015中边调试边分析性能

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 对代码进行性能分析,之前往往是一种独立的Profiling过程,现在在VS 2015中可以结 ...

  3. 不通过App Store实现ios应用分发下载安装

    最近公司的项目准备着手宣传工作了,宣传手册上要印制App的下载地址二维码,但是客户端应用还未上线,需要一种临时的方案解决应用分发下载问题,通常ios应用必须通过苹果应用商店才能下载安装,但是也可以看到 ...

  4. ARM指令学习,王明学learn

    ARM指令学习 一.算数和逻辑指令 1— MOV 数据传送指令    2.— MVN 数据取反传送指令    3.— CMP 比较指令    4.— CMN 反值比较指令    5.— TST 位测试 ...

  5. VR 相关专业词汇

    最近在看 SIGGRAPH2015 有关 VR Display and Interaction 的几篇文章,之前从来没看过有关方面的 paper,一看才发现专业词汇太多了,根本不懂啊,幸亏 Paper ...

  6. windows 2003 企业版 下载地址+序列号

    迅雷地址: thunder://QUFodHRwOi8vcy5zYWZlNS5jb20vV2luZG93c1NlcnZlcjIwMDNTUDJFbnRlcnByaXNlRWRpdGlvbi5pc29a ...

  7. HDU 5876 Sparse Graph BFS 最短路

    Sparse Graph Problem Description   In graph theory, the complement of a graph G is a graph H on the ...

  8. Linux学习笔记(21) Linux日志管理

    1. 简介 (1) 日志服务 在CentOS 6.x中日志服务已经由rsyslogd取代了原先的syslogd服务.rsyslogd日志服务更加先进,功能更多.但是不论该服务的使用,还是日志文件的格式 ...

  9. SSH框架应用解析

    一.什么是SSH SSH 不仅仅只是一个框架,而是由多个框架集成而来,是 struts+spring+hibernate的一个集成框架,是目前较流行的一种Web应用程序开源框架,结构清晰.可复用性好. ...

  10. 及其简短的Splay代码

    #include <stdio.h> #include <queue> #include <algorithm> #include <stdlib.h> ...