第一次写块状链表,发现还挺好写的,但是一点地方写错加上强制在线就会各种姿势WA/TLE/RE爆…

想法就是分块后,在每一个块上维护最大值和次大值,还在每一个块上维护一棵trie树来求异或最大值.散块直接暴力…这想法暴力吧…这道题不用考虑合并,因为最多分出(n+q)/Bsz块.详细的做法如下

对于修改一个数,首先在该块的trie数中删除该数(直接伪删,也就是让那一条路径上每个点的cnt都减1),然后再插入,接着更新最大值和次大值。

对于插入一个数,直接在trie树中插入该数,随后在块状链表中插入,更新最大值和次大值。最后判断是否要将该块拆分(如果要拆分直接暴力重构两个块即可)

对于删除一个数,trie树伪删除+块链删除+更新最大值和次大值。随后判断该块大小是否等于0(为零可以直接删掉这个块了)

对于查询最大值,首先查询出该区间内的次大值。对于完全包含的块,直接将该值丢到该块的trie树中求最大值,对于非完全包含的块,直接暴力求即可。

摘自博客AlphaINF(表示吐槽代码中统计答案的时候写的四个if语句,直接取个max,取个min不就行了吗…)

设块的大小为BBB,且设n,qn,qn,q同阶.总时间复杂度为O(n∗B+n∗n/B∗20)O(n*B+n*n/B*20)O(n∗B+n∗n/B∗20),这里的202020是在trie树上求最大值的时间复杂度.那么最小时间复杂度就是B=n/B∗20B=n/B*20B=n/B∗20,即B=20nB=\sqrt{20n}B=20n​,约是200020002000.但由于我不考虑合并,那么还可以开大一点.最后我开了250025002500

然后就BZOJBZOJBZOJ第一页了…

#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
char ch; for(;!isdigit(ch=getc()););
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
}
typedef long long LL;
const int Bsz = 2500;
const int M = 5000005;
const int LOG = 20;
int n, q;
struct node {
int mx1, mx2;
node(){ mx1 = mx2 = 0; }
node(int m1, int m2):mx1(m1), mx2(m2) {}
inline void operator +=(const node &o) {
if(o.mx1 > mx1) mx2 = mx1, mx1 = o.mx1;
else if(o.mx1 > mx2) mx2 = o.mx1;
if(o.mx2 > mx2) mx2 = o.mx2;
}
};
struct Block {
int a[Bsz+1], use, nxt, rt;
node val;
Block() {
memset(a, 0, sizeof a);
use = nxt = rt = val.mx1 = val.mx2 = 0;
}
inline void getmax() {
val = node(0, 0);
for(int i = 1; i <= use; ++i)
val += node(a[i], 0);
}
}b[100];
int ch[M][2], cnt[M], tot;
inline void add(int &rt, int x, int val) {
if(!rt) rt = ++tot;
int r = rt;
for(int bit = 1<<(LOG-1); bit; bit>>=1) {
bool i = (x&bit); cnt[r] += val;
if(!ch[r][i]) ch[r][i] = ++tot;
r = ch[r][i];
}
cnt[r] += val;
}
inline int Getmax(int rt, int x) {
int r = rt, res = 0;
for(int bit = 1<<(LOG-1); bit; bit>>=1) {
bool i = !(x&bit);
if(cnt[ch[r][i]]) res += bit;
else i ^= 1;
r = ch[r][i];
}
return res;
} int blocks = 1;
inline void modify(int pos, int val) {
int i, last;
for(i = 1; i; i = b[i].nxt)
if(b[i].use >= pos) {
last = b[i].a[pos], b[i].a[pos] = val;
add(b[i].rt, last, -1);
add(b[i].rt, val, 1);
b[i].getmax();
return; //这里忘了return...
}
else pos -= b[i].use;
}
inline void cut(int i) {
int j = ++blocks;
b[i].use = b[j].use = Bsz/2;
b[j].nxt = b[i].nxt, b[i].nxt = j;
b[i].rt = 0; b[j].rt = 0;
for(int k = 1; k <= Bsz/2; ++k) {
b[j].a[k] = b[i].a[k+Bsz/2], b[i].a[k+Bsz/2] = 0;
add(b[i].rt, b[i].a[k], 1);
add(b[j].rt, b[j].a[k], 1);
}
b[i].getmax(), b[j].getmax();
} inline void insert(int pos, int x) {
int i, pre;
for(i = 1; i; pre = i, i = b[i].nxt)
if(b[i].use < pos) pos -= b[i].use;
else break;
if(!i) i = pre, pos += b[i].use;
for(int j = b[i].use; j >= pos; --j)
b[i].a[j+1] = b[i].a[j];
b[i].a[pos] = x, ++b[i].use;
add(b[i].rt, x, 1);
b[i].val += node(x, 0);
if(b[i].use >= Bsz) cut(i);
}
inline void del(int pos) {
int i, pre = 1, x;
for(i = 1; i; pre = i, i = b[i].nxt)
if(b[i].use >= pos) {
x = b[i].a[pos]; add(b[i].rt, x, -1);
for(int j = pos; j <= b[i].use; ++j)
b[i].a[j] = b[i].a[j+1];
if(--b[i].use == 0) { b[pre].nxt = b[i].nxt; return; }
if(x >= b[i].val.mx2) b[i].getmax();
return;
}
else pos -= b[i].use;
}
inline int getmax2(int L, int R) {
int i, bot = 0, l, r; node res;
for(i = 1; i; bot += b[i].use, i = b[i].nxt) {
l = L - bot, r = R - bot;
if(l < 1 && r < 1) break;
if(l > b[i].use && r > b[i].use) continue;
l = max(l, 1), r = min(b[i].use, r);
if(l == 1 && r == b[i].use) res += b[i].val;
else for(int j = l; j <= r; ++j) res += node(b[i].a[j], 0);
}
return res.mx2;
} inline int query(int L, int R) {
int i, tmp = getmax2(L, R), bot = 0, res = 0, l, r;
for(i = 1; i; bot += b[i].use, i = b[i].nxt) {
l = L - bot, r = R - bot;
if(l < 1 && r < 1) break;
if(l > b[i].use && r > b[i].use) continue;
l = max(l, 1), r = min(b[i].use, r);
if(l == 1 && r == b[i].use) res = max(res, Getmax(b[i].rt, tmp));
else for(int j = l; j <= r; ++j) res = max(res, tmp^b[i].a[j]);
}
return res;
} int main () {
read(n), read(q);
for(int i = 1, x; i <= n; ++i)
read(x), insert(i, x);
char s[2]; int x, y, lastans = 0;
while(q--) {
while(!isalpha(s[0]=getc()));
read(x), x = (x + lastans) % n + 1;
if(s[0] == 'D') { del(x), --n; continue; }
read(y);
if(s[0] == 'F') y = (y + lastans) % n + 1;
else y = (y + lastans) % 1048576;
if(s[0] == 'I') insert(x, y), ++n;
else if(s[0] == 'C') modify(x, y);
else printf("%d\n", lastans = query(min(x, y), max(x, y)));
}
return 0;
}

BZOJ 3217: ALOEXT (块状链表套trie)的更多相关文章

  1. 【bzoj3217】ALOEXT 替罪羊树套Trie树

    题目描述 taorunz平时最喜欢的东西就是可移动存储器了……只要看到别人的可移动存储器,他总是用尽一切办法把它里面的东西弄到手. 突然有一天,taorunz来到了一个密室,里面放着一排可移动存储器, ...

  2. bzoj 3217: ALOEXT

    将此神题作为博客园的第一篇文章,至此,数据结构基本学完了(或者说数据结构轮流虐了我一次!) 人生第一道7K代码题! 没什么,就是treap套个trie,然后tle是因为一定要用指针当时p党谁会用那么丑 ...

  3. 【BZOJ3295】【块状链表+树状数组】动态逆序对

    Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...

  4. 【BZOJ 1507】【NOI 2003】&【Tyvj P2388】Editor 块状链表模板题

    2016-06-18 当时关于块状链表的想法是错误的,之前维护的是一个动态的$\sqrt{n}$,所以常数巨大,今天才知道原因TwT,请不要参照这个程序为模板!!! 模板题水啊水~~~ 第一次写块状链 ...

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

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

  6. BZOJ 4864: [BeiJing 2017 Wc]神秘物质 (块状链表/平衡树 )

    这就是一道数据结构裸题啊,最大极差就是区间最大值减最小值,最小极差就是相邻两个数差的最小值.然后平衡树splay/treap或者块状链表维护就行了. 第一次自己写块状链表,蛮好写,就是长..然后就BZ ...

  7. BZOJ 1507 Editor(块状链表)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1507 题意:一个文本编辑器,模拟以下操作: 思路:块状链表的主要操作: (1)find( ...

  8. bzoj 3809 Gty的二逼妹子序列(莫队算法,块状链表)

    [题意] 回答若干个询问,(l,r,a,b):区间[l,r]内权值在[a,b]的数有多少[种]. [思路] 考虑使用块状链表实现莫队算法中的插入与删除. 因为权值处于1..n之间,所以我们可以建一个基 ...

  9. 块状链表 bzoj 3343教主的魔法

    //块状链表//分块排序,然后每次查找时在暴力查找头和尾两个块.//中间那些块,因为有序所以只需2分查找即可.我用的是lower_pound();//插入是,也是头和尾暴力插入,中间那些加到一个累计里 ...

随机推荐

  1. [AT2062] ~K Perm Counting

    AT2602 , Luogu 求对于 \(n\) 个数的排列 , 有多少种方案满足对于所有的 \(i\) , \(|P_i - i| != K\) , 答案对 \(924844033\) 取模 . \ ...

  2. [转帖]Linux cpufreq 机制了解

    Linux cpufreq 机制了解 https://www.cnblogs.com/armlinux/archive/2011/11/12/2396780.html 引用文章链接: http://w ...

  3. 【Python】【demo实验33】【练习实例】【列表的反转】

    反转列表 我的源代码: #!/usr/bin/python # encoding=utf-8 # -*- coding: UTF-8 -*- #按照相反的顺序输出列表的各元素 l = ["t ...

  4. - RabbitMQ - 0 - 介绍、linux 和windows安装

    目录 一. 介绍 二.windows安装erlang和rabbitMQ 三.Linux安装erlang和RabbitMQ 一. 介绍 rabbitMQ 是基于 erlang 语言开发的, 为了使用 r ...

  5. Python http.server中获取Post的请求报文

    今天在自学http.server请求命令, 各个字段都很好理解, 但唯独想打印获取Post请求报文时, 被难住了, 网上找了很多帖子, 官方的文档也刷了几遍, 但没有一个明确的答复. 后来不经意间看到 ...

  6. django websocket 实现后台日志在web端展示(+前端vue设置)

    核心代码: @accept_websocket def get_log(req): if req.is_websocket(): print('收到websocket请求') with open(se ...

  7. WP8的新功能-通过一个程序来启动另一个程序

    Wp8对原来的WP7做了大量的优化...其中一个就包括Protocol Association,也就是通过uri来打开另外一个程序,这也就是说,我们可以做一个程序来启动另外一个程序了,如微信,QQ之类 ...

  8. MySQL设置自增字段

    1.MySQL每张表只能有1个自增字段,这个自增字段即可作为主键,也可用作非主键使用,但是请注意将自增字段当做非主键使用时必须为其添加唯一索引,否则系统将会报错 )将自动增长字段设置为主键 CREAT ...

  9. Visual Studio container tools require Docker to be running

    处理项目在生成时报错"Visual Studio container tools require Docker to be running" 最初win10上安装docker,项目 ...

  10. Fiddler 基础

    Fiddler 基础 来源 https://blog.csdn.net/ohmygirl/article/details/17855031 1.为什么是Fiddler? 抓包工具有很多,小到最常用的w ...