这道题能用辣鸡度搜出来的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. 第四课:PHP 变量
  2. boke练习: spring boot: security post数据时,要么关闭crst,要么添加隐藏域
  3. LeetCode 206. 反转链表 思考分析
  4. Swift 里集合类型协议的关系
  5. 作者:王海洋(1980-),男,中国科学院计算技术研究所网络数据科学与技术重点实验室、烟台中科网络技术研究所工程师。...
  6. datefromstring 转换不准确_免费的在线OCR工具,将图片内容转换为文本内容
  7. C开源hash代码uthash的用法总结(1)
  8. 两年,从月入4K到40K,从来不是努力工作,而是不断跳槽
  9. 充电枪cp信号控制板_筋膜枪究竟是不是智商税?评测后,我的回答更坚定了
  10. 我们就来看看网络算命究竟有哪些套路
  11. linux下实现对多个文件去重软件,Linux下大文件的排序和去重复
  12. 基于Python的心电图上位机诊断软件
  13. python 网络小说爬取2
  14. 鼠标右键菜单打开慢的解决方式
  15. 笔记本怎么设置WIfi热点
  16. Holder 方式的单例
  17. 第三方登陆--QQ登陆
  18. Mac升级自带PHP版本(非Homebrew方式)
  19. 大数据学习路线(包含全套视频教程)
  20. 在MarkDown中插入本地图片

热门文章

  1. 《TensorFlow技术解析与实战》——1.1 什么是人工智能
  2. SurfaceView的绘图机制
  3. Windows Apache Django 配置
  4. 一种基于annotation的Spring-mvc权限控制方法
  5. 我与WCF有个约会之牵手篇-第一个WCF示例程序
  6. yum安装php解析,详解Centos下YUM安装PHP的两种方式
  7. ER图设计数据库 练习题
  8. TCP三次握手和四次挥手详解 --- 转载
  9. Access to XMLHttpRequest at ‘url‘ from origin ‘null‘ has been blocked by CORS policy: Request header
  10. 用python做文件处理_用Python实现文件处理