这道题能用辣鸡度搜出来的treap做法只有两三篇吧,并且没有详解。。。

先看数据范围,本蒟蒻感觉nlogn过不了啊。。。 [主要是我是大常数选手]

其实可以勉强过,

跪烂了那些只跑1s多的神犇%%%

首先,四百万次的插入,如果你每次都申请一个新的空间,肯定是要MLE的。

我们注意到数列中最多只有五十万个元素,也就是说我们最多同时用到五十万个空间。那么可以这样处理:维护一个栈,删除时将要删除的元素加到栈里,每次申请新的节点时先看栈里还有没有元素,如果有,那么将栈顶出栈,用于新申请的元素,否则新申请空间,,

Treap *newnode (int xxx) {if (top) return new (stk[top--]) Treap (xxx, Null);return new (pool++) Treap (xxx, Null);
}

求区间最大值的话,对于一个节点多维护如下信息,以这个节点为根的子树代表的序列,最右边一段连续数值最大和是多少,最左边一段连续数值的最大和是多少,这段区间最大的一段连续子序列和是多少。(分别记为rmax, lmax, mmax)当前节点的值记为data, 当前节点所代表的子树的元素和为sum,size代表该子树元素个数。

rmax可以这样转移 : 它等于 Max (右儿子的rmax,data + 右儿子的sum + Max (左儿子的rmax,0))。

如图,DE代表当前节点的那个元素,BC为当前节点代表的子树,BD代表当前节点的左儿子所代表的子树,EC代表当前节点的右儿子所代表的子树,如果BC这段区间的rmax的那段区间在EC中,那么它就是CE的rmax,如果不在EC中,即左端点在E的左边,那么它就等于BE这段区间的rmax加上EC这段区间的和,BE这段区间的rmax怎么求呢?首先DE必须要选(因为左端点在e左边),那么我们就可以看BD的rmax了。如果BD的rmax < 0 ,那么选了他会让BC的rmax变小,不如不选。所以可以得出上面的式子。

选右儿子同理。那么当前节点的mmax = Max (当前节点的lmax,当前节点的rmax,左儿子的mmax,右儿子的mmax,Max(0,左儿子的rmax)+Max(0,右儿子的lmax)+data)

至于为什么这样,就留给你们自己思考啦。

  void update () {if (l != Null) l -> pushdown ();if (r != Null) r -> pushdown ();size = l -> size + r -> size + 1;sum = l -> sum + r -> sum + data;lmax = data + std :: max (r -> lmax, 0);rmax = data + std :: max (l -> rmax, 0); if (l != Null) lmax = std :: max (l -> lmax, l -> sum + lmax);if (r != Null) rmax = std :: max (r -> rmax, r -> sum + rmax);mmax = std :: max (std :: max (l -> mmax, r -> mmax), std :: max (std :: max(lmax, rmax), std :: max (l -> rmax, 0) + std :: max (r -> lmax, 0) + data));}

那么怎样下放标记呢,对于翻转的标记,把左右儿子交换,将lmax , rmax交换即可。对于覆盖的标记,就是把data改成标记的值,sum改成data*size。如果data是大于零的,那么这段区间的最大值就应该是sum。(即lmax = rmax = mmax = sum) 否则,由于至少要选一个元素,那么最大值就为data (即lmax = rmax = mmax = data)。

  void pushdown () {if (l1) {l -> l1 ^= 1; r -> l1 ^= 1; l1 ^= 1;std :: swap (l, r);std :: swap (lmax, rmax); }if (l21) {l -> l21 = r -> l21 = true;l -> l22 = r -> l22 = l22;l21 = false;data = l22;sum = data * size;lmax = rmax = mmax = l22 > 0 ? sum : data;}}

最后上代码,反正细节挺多的。。。 我语文不好,感觉对不住观众朋友QAQ

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<iostream>
#include<algorithm>
#include<cctype>
#include<cmath>const int N = 5e5 + 9;int top, n, m;struct Treap *Null;struct Treap {int data, sum, size, hr, lmax, rmax, mmax; bool l1, l21; int l22;Treap *l, *r;Treap () {}Treap (int data, Treap *fl) : data(data), sum(data), size(1), hr(rand()), lmax(data), rmax(data), mmax(data), l1(0), l21(0), l(fl), r(fl) {}void update () {if (l != Null) l -> pushdown ();if (r != Null) r -> pushdown ();size = l -> size + r -> size + 1;sum = l -> sum + r -> sum + data;lmax = data + std :: max (r -> lmax, 0);rmax = data + std :: max (l -> rmax, 0); if (l != Null) lmax = std :: max (l -> lmax, l -> sum + lmax);if (r != Null) rmax = std :: max (r -> rmax, r -> sum + rmax);mmax = std :: max (std :: max (l -> mmax, r -> mmax), std :: max (std :: max(lmax, rmax), std :: max (l -> rmax, 0) + std :: max (r -> lmax, 0) + data));}void pushdown () {if (l1) {l -> l1 ^= 1; r -> l1 ^= 1; l1 ^= 1;std :: swap (l, r);std :: swap (lmax, rmax); }if (l21) {l -> l21 = r -> l21 = true;l -> l22 = r -> l22 = l22;l21 = false;data = l22;sum = data * size;lmax = rmax = mmax = l22 > 0 ? sum : data;}}
}*root, meme[N], *pool = meme, *stk[N];void rec (Treap *x) {if (x == Null) return ;rec (x -> l);rec (x -> r);stk[++top] = x;
}Treap *newnode (int xxx) {if (top) return new (stk[top--]) Treap (xxx, Null);return new (pool++) Treap (xxx, Null);
}Treap *Merge (Treap *A, Treap *B) {if (A == Null) return B;if (B == Null) return A;if (A -> hr > B -> hr) {B -> pushdown ();B -> l = Merge (A, B -> l);B -> update ();return B;} else {A -> pushdown ();A -> r = Merge (A -> r, B);A -> update ();return A;}
}using std :: pair;
typedef pair <Treap *, Treap *> Droot;Droot Split (Treap *x, int k) {if (x == Null) return Droot (Null, Null);Droot y; x -> pushdown ();if (x -> l -> size >= k) {y = Split (x -> l, k);x -> l = y . second;x -> update ();y . second = x;} else {y = Split (x -> r, k - x -> l -> size - 1);x -> r = y . first;x -> update ();y . first = x;}return y;
}int num; bool fl; char a;int getin () {num = fl = 0;for (a = getchar (); a < '0' || a > '9'; a = getchar()) if (a == '-') fl = true;for (; a >= '0' && a <= '9'; a = getchar()) num = (num << 3) + (num << 1) + a - '0';if (fl) num = -num;return num;
}Treap *Build () {Treap *x, *last; stk[1] = Null;for (int i = 1; i <= n; ++i) {x = new (pool++) Treap (getin (), Null); last = Null;while (top && stk[top] -> hr > x -> hr) {stk[top] -> update ();last = stk[top--];}if (top) stk[top] -> r = x;x -> l = last;stk[++top] = x;}while (top) stk[top--] -> update ();return stk[1];
}Droot clc2, clc1;
char opt[20]; Treap *clc3;int main () {Null = new Treap (-0x7fffffff, NULL); Null -> size = Null -> sum = 0;n = getin (); m = getin (); root = Build ();while (m--) {scanf ("%s", opt);if (opt[2] == 'X') printf ("%d\n", root -> mmax);else if (opt[2] == 'S') {clc1 = Split (root, getin());clc3 = Null;for (int i = getin(); i; --i) clc3 = Merge (clc3, newnode (getin()));root = Merge (clc1 . first, Merge (clc3, clc1 . second));} else {clc1 = Split (root, getin() - 1);clc2 = Split (clc1 . second, getin());if (opt[2] == 'K') clc2 . first -> l21 = true, clc2 . first -> l22 = getin ();if (opt[2] == 'V') clc2 . first -> l1 = true;if (opt[2] == 'T') printf ("%d\n", clc2 . first -> sum);if (opt[2] == 'L') rec (clc2 . first), root = Merge (clc1 . first, clc2 . second);else root = Merge (clc1 . first, Merge (clc2 . first, clc2 . second));}}return 0;
}

转载于:https://www.cnblogs.com/dcoi-king/p/7491436.html

[noi2005][treap]序列维护相关推荐

  1. bzoj 1798 5039: [Jsoi2014]序列维护(线段树)

    5039: [Jsoi2014]序列维护 Time Limit: 20 Sec  Memory Limit: 256 MB Submit: 17  Solved: 14 [Submit][Status ...

  2. 【FHQ treap】维护书架(金牌导航 无旋式treap-1)

    维护书架 金牌导航 无旋式treap-1 题目大意 给出一个序列a,编号为1~n,让你做若干操作,操作有五种: 1.把第x个数放在最前面 2.把第x个数放在最后面 3.把第x个数和第x±1x\pm 1 ...

  3. bzoj5039:[Jsoi2014]序列维护

    做做bzoj上的新题(不存在的) 同bzoj1798: [Ahoi2009]维护序列,样例都一样的...我能想象到的唯一的新的考察意义就是模数是2e9不是1e9,于是加法的时候需要转long long ...

  4. 【JSOI2014】【BZOJ5039】序列维护(线段树模板)

    problem 已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 solution 区间修改+区间查询. 维护两个LazyTa ...

  5. 2017.9.13 序列维护 思考记录

    终于不对拍1A线段树了.太不容易了 虽然这题挺裸的,省选福利,记住先乘后加的原则就可以搞了 注意位运算和取模的优先级,不要乱了,注意代码的位置问题 码(发现我的线段树非常瘦): #include< ...

  6. 模板 - FHQ - treap 无旋平衡树

    整理的算法模板合集: ACM模板 目录 FQH - treap 无旋平衡树 按权值分裂 按排名分裂 文艺平衡树 可持久化序列 FQH - treap 无旋平衡树 operator 1 : 插入一个数 ...

  7. 【bzoj5110】[CodePlus2017]Yazid 的新生舞会 Treap

    题目描述 求一个序列所有的子区间,满足区间众数的出现次数大于区间长度的一半. 输入 第一行2个用空格隔开的非负整数n,type,表示序列的长度和数据类型.数据类型的作用将在子任务中说明. 第二行n个用 ...

  8. FHQ Treap 总结

    [前言(一堆废话)] 目前 OI 竞赛中两大主流平衡树之一就是 FHQ Treap(另一个是 Splay). 普通 BST 的中序遍历中,val 值构成一个单调递增的序列. Treap 在 BST 的 ...

  9. FHQ Treap及其可持久化与朝鲜树式重构

    FHQ Treap,又称无旋treap,一种不基于旋转机制的平衡树,可支持所有有旋treap.splay等能支持的操作(只有在LCT中会比splay复杂度多一个log).最重要的是,它是OI中唯一一种 ...

  10. luogu P2596 [ZJOI2006]书架(平衡树、无旋treap(按排名分裂)一些更复杂的操作)

    P2596 [ZJOI2006]书架 无旋treap可以维护一棵树的中序遍历结果.但是不支持通过编号来找节点.于是在无旋treap的基础上,我维护了每个节点的父亲,这样就可以求出一个节点是中序遍历中的 ...

最新文章

  1. Eclipse 3.6 更新中文语言包的方法
  2. 【异常】 ‘ascii‘ codec can‘t decode byte 0xe8 in position 2: ordinal not in range(128)
  3. TCP IP基础知识的复习
  4. 译文 | 与TensorFlow的第一次接触第二篇:线性回归
  5. 数据库笔记03:管理数据表中的数据
  6. 深圳出差 第二天【原创】
  7. 详解Android中AsyncTask的使用
  8. 【C#】图片处理(底片,黑白,锐化,柔化,浮雕,雾化)
  9. 双系统linux安装cetos,电脑安装windows和centOS系统双系统
  10. java socket 发对象_Java Socket 发送对象
  11. ssh-hostbased配置方法
  12. GitGithub 备忘录
  13. 阿里巴巴年度技术总结 - 人工智能在搜索的应用和实践
  14. 微信小程序登录获取手机号获取不到偶发性问题
  15. XCTF 华为云专场 qemuzzz
  16. 匈牙利命名法(Hungarian Notation)
  17. 中兴 Axon 40 Ultra参数评测 中兴 Axon 40 Ultra配置怎么样 中兴 Axon 40 Ultra值得买吗
  18. Python编程 | 系统编程 | 脚本运行上下文 | 标准流
  19. STM32点亮第一盏灯
  20. 实用干货|腾讯内部几近满分的项目管理方法(PPT)

热门文章

  1. [HTML5和Flash视频播放器]Video.js 学习笔记(一 ) HLS库:videojs-contrib-hls
  2. 理解和使用 Unity UI 系统(canvas和CanvasScaler )
  3. HDOJ2005 ( 第几天? ) 【水题】
  4. phone html5,[操作系统]HTML5 On Windows Phone (2) windows phone mango上使用HTML5并与HTML5交互...
  5. python如何删除对象属性_如何销毁python中属性中的对象?
  6. text 热敏打印机_ESC/POS热敏打印机示例
  7. 一对多关联关系映射和设置级联属性
  8. git和github的基本使用
  9. 自定义注解和SpEL表达式实现功能强大的无侵入式的日志功能
  10. 动物之美计算机教案,清华大学版六年级上册信息技术教案第三课 动物之美——图像分类管理.pdf...