第一次写块状链表,发现还挺好写的,但是一点地方写错加上强制在线就会各种姿势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第一页了…

  1. #include <vector>
  2. #include <cstdio>
  3. #include <cctype>
  4. #include <cstring>
  5. #include <algorithm>
  6. using namespace std;
  7. char cb[1<<15],*cs=cb,*ct=cb;
  8. #define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
  9. template<class T>inline void read(T &res) {
  10. char ch; for(;!isdigit(ch=getc()););
  11. for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0');
  12. }
  13. typedef long long LL;
  14. const int Bsz = 2500;
  15. const int M = 5000005;
  16. const int LOG = 20;
  17. int n, q;
  18. struct node {
  19. int mx1, mx2;
  20. node(){ mx1 = mx2 = 0; }
  21. node(int m1, int m2):mx1(m1), mx2(m2) {}
  22. inline void operator +=(const node &o) {
  23. if(o.mx1 > mx1) mx2 = mx1, mx1 = o.mx1;
  24. else if(o.mx1 > mx2) mx2 = o.mx1;
  25. if(o.mx2 > mx2) mx2 = o.mx2;
  26. }
  27. };
  28. struct Block {
  29. int a[Bsz+1], use, nxt, rt;
  30. node val;
  31. Block() {
  32. memset(a, 0, sizeof a);
  33. use = nxt = rt = val.mx1 = val.mx2 = 0;
  34. }
  35. inline void getmax() {
  36. val = node(0, 0);
  37. for(int i = 1; i <= use; ++i)
  38. val += node(a[i], 0);
  39. }
  40. }b[100];
  41. int ch[M][2], cnt[M], tot;
  42. inline void add(int &rt, int x, int val) {
  43. if(!rt) rt = ++tot;
  44. int r = rt;
  45. for(int bit = 1<<(LOG-1); bit; bit>>=1) {
  46. bool i = (x&bit); cnt[r] += val;
  47. if(!ch[r][i]) ch[r][i] = ++tot;
  48. r = ch[r][i];
  49. }
  50. cnt[r] += val;
  51. }
  52. inline int Getmax(int rt, int x) {
  53. int r = rt, res = 0;
  54. for(int bit = 1<<(LOG-1); bit; bit>>=1) {
  55. bool i = !(x&bit);
  56. if(cnt[ch[r][i]]) res += bit;
  57. else i ^= 1;
  58. r = ch[r][i];
  59. }
  60. return res;
  61. }
  62. int blocks = 1;
  63. inline void modify(int pos, int val) {
  64. int i, last;
  65. for(i = 1; i; i = b[i].nxt)
  66. if(b[i].use >= pos) {
  67. last = b[i].a[pos], b[i].a[pos] = val;
  68. add(b[i].rt, last, -1);
  69. add(b[i].rt, val, 1);
  70. b[i].getmax();
  71. return; //这里忘了return...
  72. }
  73. else pos -= b[i].use;
  74. }
  75. inline void cut(int i) {
  76. int j = ++blocks;
  77. b[i].use = b[j].use = Bsz/2;
  78. b[j].nxt = b[i].nxt, b[i].nxt = j;
  79. b[i].rt = 0; b[j].rt = 0;
  80. for(int k = 1; k <= Bsz/2; ++k) {
  81. b[j].a[k] = b[i].a[k+Bsz/2], b[i].a[k+Bsz/2] = 0;
  82. add(b[i].rt, b[i].a[k], 1);
  83. add(b[j].rt, b[j].a[k], 1);
  84. }
  85. b[i].getmax(), b[j].getmax();
  86. }
  87. inline void insert(int pos, int x) {
  88. int i, pre;
  89. for(i = 1; i; pre = i, i = b[i].nxt)
  90. if(b[i].use < pos) pos -= b[i].use;
  91. else break;
  92. if(!i) i = pre, pos += b[i].use;
  93. for(int j = b[i].use; j >= pos; --j)
  94. b[i].a[j+1] = b[i].a[j];
  95. b[i].a[pos] = x, ++b[i].use;
  96. add(b[i].rt, x, 1);
  97. b[i].val += node(x, 0);
  98. if(b[i].use >= Bsz) cut(i);
  99. }
  100. inline void del(int pos) {
  101. int i, pre = 1, x;
  102. for(i = 1; i; pre = i, i = b[i].nxt)
  103. if(b[i].use >= pos) {
  104. x = b[i].a[pos]; add(b[i].rt, x, -1);
  105. for(int j = pos; j <= b[i].use; ++j)
  106. b[i].a[j] = b[i].a[j+1];
  107. if(--b[i].use == 0) { b[pre].nxt = b[i].nxt; return; }
  108. if(x >= b[i].val.mx2) b[i].getmax();
  109. return;
  110. }
  111. else pos -= b[i].use;
  112. }
  113. inline int getmax2(int L, int R) {
  114. int i, bot = 0, l, r; node res;
  115. for(i = 1; i; bot += b[i].use, i = b[i].nxt) {
  116. l = L - bot, r = R - bot;
  117. if(l < 1 && r < 1) break;
  118. if(l > b[i].use && r > b[i].use) continue;
  119. l = max(l, 1), r = min(b[i].use, r);
  120. if(l == 1 && r == b[i].use) res += b[i].val;
  121. else for(int j = l; j <= r; ++j) res += node(b[i].a[j], 0);
  122. }
  123. return res.mx2;
  124. }
  125. inline int query(int L, int R) {
  126. int i, tmp = getmax2(L, R), bot = 0, res = 0, l, r;
  127. for(i = 1; i; bot += b[i].use, i = b[i].nxt) {
  128. l = L - bot, r = R - bot;
  129. if(l < 1 && r < 1) break;
  130. if(l > b[i].use && r > b[i].use) continue;
  131. l = max(l, 1), r = min(b[i].use, r);
  132. if(l == 1 && r == b[i].use) res = max(res, Getmax(b[i].rt, tmp));
  133. else for(int j = l; j <= r; ++j) res = max(res, tmp^b[i].a[j]);
  134. }
  135. return res;
  136. }
  137. int main () {
  138. read(n), read(q);
  139. for(int i = 1, x; i <= n; ++i)
  140. read(x), insert(i, x);
  141. char s[2]; int x, y, lastans = 0;
  142. while(q--) {
  143. while(!isalpha(s[0]=getc()));
  144. read(x), x = (x + lastans) % n + 1;
  145. if(s[0] == 'D') { del(x), --n; continue; }
  146. read(y);
  147. if(s[0] == 'F') y = (y + lastans) % n + 1;
  148. else y = (y + lastans) % 1048576;
  149. if(s[0] == 'I') insert(x, y), ++n;
  150. else if(s[0] == 'C') modify(x, y);
  151. else printf("%d\n", lastans = query(min(x, y), max(x, y)));
  152. }
  153. return 0;
  154. }

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. [转载]ASP.NET Core文件上传与下载(多种上传方式)

    ASP.NET Core文件上传与下载(多种上传方式)   前言 前段时间项目上线,实在太忙,最近终于开始可以研究研究ASP.NET Core了. 打算写个系列,但是还没想好目录,今天先来一篇,后面在 ...

  2. 【Funny Things】001——QQ循环发送消息

    借用Java的Robot类库中的键鼠模拟的方法,执行这个操作,首先切换到QQ界面,然后循环粘贴,回车发送消息. package newtest; import java.awt.*; import j ...

  3. Chrome浏览器控制台报 POST http://*** net::ERR_BLOCKED_BY_CLIENT

    开发项目广告模块时,遇到前端提交的请求后台拿不到,好像被什么拦截了,查看了过滤器,拦截器都无错误,且请求也到不了拦截器,chrome浏览器报:ERR_BLOCKED_BY_CLIENT错误 搞腾一半天 ...

  4. PHP学习之PHP trait解析

    自PHP5.4.0起,PHP实现了一种代码复用的方法,称为trait. 众所周知,PHP中是单继承的,trait是为类似PHP的单继承语言而准备得一种代码复用机制.trait为了减少单继承语言的限制, ...

  5. 编写程序来实现实现strcat()功能

    strcat(字符数组1,字符串2) 字符串2的内容复制连接在字符数组1的后面,其返回值为字符数组1的地址 /* strcat(字符数组1,字符串2) 字符串2的内容复制连接在字符数组1的后面,其返回 ...

  6. 记笔记的软件(vnote)

    前面我们已经把我们的 Ubuntu 系统在物理机上运行起来了,也做了一些简单的优化,教了大家怎么使用 Ubuntu 系统自带的应用商店和 apt 安装和卸载软件.接着我们安装了搜狗输入法,现在我们的系 ...

  7. C#应用笔记

    1.ref关键字.out关键字——引用传递参数 2.什么时候用DateReader,什么时候用DateSet呢? 3.is操作符.as操作符的使用 4.Eval方法和Bind方法的区别 5.Serve ...

  8. Spark机器学习API之特征处理(二)

    Spark机器学习库中包含了两种实现方式,一种是spark.mllib,这种是基础的API,基于RDDs之上构建,另一种是spark.ml,这种是higher-level API,基于DataFram ...

  9. C# 校验车架号(VIN码)第9位是否有效算法

    public static bool checkVIN(string vin) { //VIN码从第1位到第17位的“加权值”: Dictionary<int, int> vinMapWe ...

  10. case when语法

    Case具有两种格式.简单Case函数和Case搜索函数. --简单Case函数: CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END ...