[noi2005][treap]序列维护

来源:互联网 发布:单页面网站源码 编辑:程序博客网 时间:2024/05/18 00:51

这道题能用辣鸡度搜出来的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;}


1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机酷狗音乐下载收费怎么办 咪咕视频静音了怎么办 卡西欧自拍神器死机了怎么办 手机一自拍就死机怎么办 微信怎么黑屏了怎么办 宝宝睡袋买大了怎么办 社保中间断了一年怎么办 京东阅读换手机怎么办 酷狗自动续费怎么办 qq音乐下载需要钱怎么办 电脑播放音乐没声音怎么办 酷狗账号注销了怎么办 电脑酷狗音乐没有声音怎么办 百度云的视频被净网怎么办 v380用户名或密码错误怎么办 课堂派没签到的怎么办 微信加密忘记了怎么办 视频容量太大上传不了视频怎么办 小米手机打不开主页面怎么办 qq离线文件过期了怎么办 百度云有转存任务正在进行怎么办 港版索尼手机的浏览器怎么办 手机下载文件不能直接打开怎么办 上传到电脑视频打不开了怎么办 百度云播放很卡怎么办 百度云视频很卡怎么办 考虫课程过期了怎么办 私教课程过期了怎么办 在异地交的社保怎么办 1岁宝宝吃粉笔怎么办 宝宝吃了彩色笔怎么办 宝宝吃了彩笔水怎么办 熹妃q传忘记密码怎么办 云课堂2忘记密码怎么办 云课堂密码忘了怎么办 小米云存储空间已经满怎么办 苹果手机云备份空间不足怎么办 办信用卡不知道公司电话怎么办 办信用卡不知道单位电话怎么办 朋友沉迷网络游戏怎么办英文作文 平板的密码忘了怎么办