2018年论文题,上接loj2506,主要是论文中的第4章,也可快速跳至原题解

5.平衡树的嵌套问题

平衡树嵌套

所谓平衡树嵌套,就是若干棵平衡树,其中若干棵平衡树的根会指向另一颗平衡树上的一个节点

定义一棵平衡树的$W$为其子树内所有节点的$w_{x}$之和,再定义$w_{x}$为上述指向其的根的平衡树的$W$之和加1

(这两者定义并不嵌套,显然可以按层去计算$w_{x}$和$W$)

如果在一个平衡树中访问节点$x$的复杂度为$o(\log\frac{W}{w_{x}})$,那么就有以下结论——

定理9:以此法从全局的根访问一个节点$x$,复杂度为$o(k+\log n)$(其中$k$为从$x$到全局的根路径上所经过的平衡树数量,也即层数)

证明:从下往上依次记录在每一棵平衡树中的复杂度,即$\sum_{i=1}^{k}\log\frac{W_{i}}{w_{i}}+1$

根据定义,有$w_{i}\ge W_{i-1}$,不妨将其放缩,即$\sum_{i=1}^{k}\log\frac{W_{i}}{W_{i-1}}+1\sim o(k+\log n)$

而如果没有上述性质,即每一次都是$o(\log n)$的,那么总复杂度也就是$o(k\log n)$

下面,我们将要分别考虑Treap和Splay如何做到$o(\log\frac{W}{w_{x}})$的复杂度

Treap

考虑一个简单的构造,令节点$x$的随机值为$w_{x}$个随机值中的最大值

**定理10:**以此法随机并维护,节点$x$的期望深度为$o(\log\frac{W}{w_{x}})$

**证明:**为了方便表示,将节点按元素从小到大依次记为$a_{1},a_{2},...,a_{n}$,权值依次为$w_{1},w_{2},...,w_{n}$

类似前面,节点$a_{x}$的期望深度也就是有所有节点是其祖先的概率之和,即
$$
\sum_{i=1}^{x-1}\frac{w_{i}}{\sum_{j=i}^{x}w_{j}}+\sum_{i=x+1}^{n}\frac{w_{i}}{\sum_{j=x}^{i}w_{j}}
$$
(关于这里的概率,实际上也就是$\sum_{j=i}^{x}w_{j}$个随机值中最大值在$i$随机的$w_{i}$个数中,即此式)

将其展开,并进行放缩,即
$$
\le \sum_{i=1}^{x-1}\sum_{k=1}^{w_{i}}\frac{1}{\sum_{j=i+1}^{x}w_{j}+k}+\sum_{i=x+1}^{n}\sum_{k=1}^{w_{i}}\frac{1}{\sum_{j=x}^{i-1}w_{j}+k}
$$
每一次也就是一个区间,且这些区间恰好是连续的,即
$$
\sum_{i=w_{x}+1}^{\sum_{j=1}^{x}w_{j}}\frac{1}{i}+\sum_{i=w_{x}+1}^{\sum_{j=x}^{n}w_{j}}\frac{1}{i}\sim o(\log \frac{W}{w_{x}})
$$
当然这样随机的复杂度为$o(W)$,在某些情况下可能无法接受

一个简单的做法是记录子树的$w$之和,并以此为概率进行比较

另外还有一个比较有趣的做法,来实现这个随机——

对于一个随机变量$X$,令$P(x)$表示随机变量$X\le x$的概率

再构造一个函数$f(x)$,在其定义域中有$P(x)$的概率为函数值小于等于$x$,那么$f(x)$也就是一个随机$X$的函数,即只要在其定义域中等概率随机一个$x$,取$X=f(x)$即可

事实上,取$f(x)=P^{-1}(x)$即可,代入本题中,即$P(x)=x^{w}$,那么$f(x)=x^{\frac{1}{w}}$

考虑$x^{\frac{1}{w_{1}}}<y^{\frac{1}{w_{2}}}$的概率,也就是$x^{w2}<y^{w1}$

Splay

定理11:对节点$x$进行Splay操作的均摊复杂度为$o(\log\frac{W}{w_{x}})$

证明:令每一个节点的$sz_{x}$为子树内所有节点的权值之和,类似于结论2的证明,可以得到该结论

6.平衡树嵌套的应用

树链剖分

用平衡树来维护一条重链,对于顶端节点不是根节点的重链,将其连向顶端节点的父亲

根据轻边的性质,不难证明$k\sim o(\log n)$,因此单次复杂度仅为$o(\log n)$,事实上大部分使用线段树维护树链剖分都可以通过这样的技巧优化来减少一个$\log$

LCT

定理12:LCT的单次操作时间复杂度为均摊$o(\log n)$

证明:对于$o(k+\log n)$的复杂度,后者显然可以忽略, 对前者$k$进行势能分析:

(以下描述中,轻重儿子是根据子树大小确定,实虚儿子是根据LCT确定)

定义当前这个结构的势能为其中实儿子与重儿子不同的节点数(重儿子任取),考虑将一个节点到根路径上所有虚边都变为实边,对这个节点分类讨论:

1.若其是轻儿子,显然这样的节点数不多于$\log n$个,且每一个节点最多导致1次操作以及1个势能,即单个节点是$o(1)$的,那么总共即$o(\log n)$的

2.若其是重儿子,那么将实儿子修改为其,会导致势能减小1,即本次操作无贡献

且由于势能大小为不超过$n$的非负整数,因此即在最外面还会有一个$o(n)$,也可以接受

(另外,这也就说明了LCT上访问一个节点必须access,而不能直接去访问)

关于Treap维护LCT

看似Treap也可以维护LCT,但实际上并不能实现

这是因为在维护过程中,我们需要修改一个节点的$w_{x}$,在Splay中我们只需要将其Splay至根即可,但在Treap中我们要给其新的随机值并进行调整

首先,直接暴力删除再插入,也可以做到$o(\log n)$,那么也就是单次$o(k\log n)$,对$k$进行一样的均摊分析,也就得到了Treap维护LCT单次操作是$o(\log^{2}n)$的

当然,我们也可以略微优化这个调整(但似乎并不能该边其维护LCT的复杂度),若其随机值增加即将其下旋(将随机值较小的旋上来),否则将其上旋

那么这样的复杂度也就是其与最终状态的期望深度差,有以下结论——

定理13:假设其权值由$w$变为$w'$,则其期望深度差为$\log\frac{\max(w,w')}{\min(w,w')}$

证明:与之前一样,假设权值依次为$w_{1},w_{2},...,w_{n}$,且其中$w_{x}$的权值增加了$\Delta$($\Delta\ge 0$),我们要证明的也就是深度差是$o(\log \frac{w_{x}+\Delta}{w_{x}})$

深度也用每一个点的概率来表示,即
$$
\sum_{i=1}^{x-1}\frac{w_{i}}{\sum_{j=i}^{x}w_{j}}-\frac{w_{i}}{\sum_{j=i}^{x}w_{j}+\Delta}+\sum_{i=x+1}^{n}\frac{w_{i}}{\sum_{j=x}^{i}w_{j}}-\frac{w_{i}}{\sum_{j=x}^{i}w_{j}+\Delta}
$$
注意到$f(x)=\frac{1}{x}-\frac{1}{x+\Delta}$在$x>0$时是递减的,那么就可以与之前一样,将前者表示为
$$
\frac{w_{i}}{\sum_{j=i}^{x}w_{j}}-\frac{w_{i}}{\sum_{j=i}^{x}w_{j}+\Delta}=w_{i}\times f(\sum_{j=i}^{x}w_{j})\le \sum_{k=1}^{w_{i}}f(\sum_{j=i+1}^{x}w_{j}+k)=\sum_{i=w_{x}+1}^{\sum_{j=1}^{x}w_{j}}f(i)
$$
将$f(x)=\frac{1}{x}-\frac{1}{x+\Delta}$代入后分别计算,即$o(\log\frac{S}{w_{x}}-\log\frac{S}{w_{x}+\Delta})=o(\log\frac{w_{x}+\Delta}{w_{x}})$(其中$S=\sum_{j=1}^{x}w_{j}$)

后半部分类似,也可以得到该结论,另外将$\Delta<0$看作反过来即可

这个结论虽然并不能让Treap维护LCT的理论复杂度更优,但可能会有用处

原题解:

将表达式其看作一个$2n-1$的序列,建立一棵Treap使得其中序遍历即该序列,并且保证父亲节点运算优先级不大于儿子(其中元素看作$k+1$级的操作),那么不难证明此时不断合并即可得到结果

进一步的,考虑对于与这棵Treap根节点相连的连通块,必然是优先级最低的所有操作,且之后剩下的若干个也同样满足此性质Treap,这也就构成了嵌套的关系,根据定理9每一个节点深度是$o(k+\log n)$的

(一个节点子树内所有节点的$w$之和,不难发现也就是其Treap的子树大小,以此为概率进行比较)

综上,使用合并和分裂维护,复杂度都是深度,即$o(k+\log n)$,可以通过

  1 #include "expr.h"
2 #include<bits/stdc++.h>
3 using namespace std;
4 #define N 20005
5 #define s(p) f[k].ch[p]
6 struct node{
7 int op,sz,tag,ch[2];
8 Data val;
9 bool operator < (const node &k)const{
10 return (op<k.op)||(op==k.op)&&(rand()%(sz+k.sz)<sz);
11 }
12 }f[N*1000];
13 int V,m,a,b,c,rt[N];
14 int New(int k){
15 f[++V]=f[k];
16 return V;
17 }
18 void rev(int &k){
19 k=New(k);
20 f[k].tag^=1;
21 swap(s(0),s(1));
22 }
23 void up(int k){
24 f[k].sz=f[s(0)].sz+f[s(1)].sz+1;
25 if ((s(0))&&(s(1)))f[k].val=F(f[s(0)].val,f[s(1)].val,f[k].op);
26 else{
27 if (s(0))f[k].val=f[s(0)].val;
28 if (s(1))f[k].val=f[s(1)].val;
29 }
30 }
31 void down(int k){
32 if (f[k].tag){
33 if (s(0))rev(s(0));
34 if (s(1))rev(s(1));
35 f[k].tag=0;
36 }
37 }
38 int merge(int x,int y){
39 if ((!x)||(!y))return x+y;
40 down(x),down(y);
41 int k;
42 if (f[x]<f[y]){
43 k=New(x);
44 s(1)=merge(f[x].ch[1],y);
45 }
46 else{
47 k=New(y);
48 s(0)=merge(x,f[y].ch[0]);
49 }
50 up(k);
51 return k;
52 }
53 void split(int k,int x,int &a,int &b){
54 if (!k){
55 a=b=0;
56 return;
57 }
58 down(k);
59 if (x<=f[s(0)].sz){
60 b=New(k);
61 split(s(0),x,a,f[b].ch[0]);
62 up(b);
63 }
64 else{
65 a=New(k);
66 split(s(1),x-f[s(0)].sz-1,f[a].ch[1],b);
67 up(a);
68 }
69 }
70 void init(int id,int n,int m,int k,const Data *a,const int *op){
71 srand(time(0));
72 V=2*n-1;
73 for(int i=1;i<2*n;i++){
74 if (i%2==0)f[i].op=op[i/2];
75 else{
76 f[i].val=a[i/2];
77 f[i].op=k+1;
78 }
79 f[i].sz=1;
80 rt[0]=merge(rt[0],i);
81 }
82 }
83 Data modify_data(int id,int x,Data y){
84 x=x*2+1;
85 split(rt[id],x-1,a,b);
86 split(b,1,b,c);
87 b=New(b);
88 f[b].val=y;
89 rt[++m]=merge(merge(a,b),c);
90 return f[rt[m]].val;
91 }
92 Data modify_op(int id,int x,int y){
93 x*=2;
94 split(rt[id],x-1,a,b);
95 split(b,1,b,c);
96 b=New(b);
97 f[b].op=y;
98 rt[++m]=merge(merge(a,b),c);
99 return f[rt[m]].val;
100 }
101 Data reverse(int id,int x,int y){
102 x=x*2+1,y=y*2+1;
103 split(rt[id],x-1,a,b);
104 split(b,y-x+1,b,c);
105 rev(b);
106 rt[++m]=merge(merge(a,b),c);
107 return f[rt[m]].val;
108 }

(似乎被卡了操作次数)

[uoj173]鏖战表达式的更多相关文章

  1. wc2016鏖战表达式(可持久treap)

    由运算符有优先级可以想到先算优先级小的,然后两边递归,但符号比较少,有大量相同的,同级之间怎么办呢?因为运算符满足结合律,同级之间选一个然后两边递归也是没问题的,然后我们想到用fhqtreap进行维护 ...

  2. WC2016自测

    挑战NPC 原题链接 爆搜20分,贪心10分,网络流30分 //挑战NPC #include <cstdio> #include <cstring> #include < ...

  3. 2017-12 CDQZ集训(已完结)

    从联赛活了下来(虽然分数倒一……),接下来要去CDQZ集训啦…… DAY -2 2017-12-16 被老师安排负责一部分同学的住宿以及安排…… 抓紧时间继续学习,LCT真好玩啊真好玩…… 晚上放假了 ...

  4. 转:鏖战双十一-阿里直播平台面临的技术挑战(webSocket, 敏感词过滤等很不错)

    转自:http://www.infoq.com/cn/articles/alibaba-broadcast-platform-technology-challenges 鏖战双十一-阿里直播平台面临的 ...

  5. 【.net 深呼吸】细说CodeDom(2):表达式、语句

    在上一篇文章中,老周厚着脸皮给大伙介绍了代码文档的基本结构,以及一些代码对象与CodeDom类型的对应关系. 在评论中老周看到有朋友提到了 Emit,那老周就顺便提一下.严格上说,Emit并不是针对代 ...

  6. 你知道C#中的Lambda表达式的演化过程吗?

    那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...

  7. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  8. Linq表达式、Lambda表达式你更喜欢哪个?

    什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...

  9. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

随机推荐

  1. LinkedList-常用方法以及双向链表的理解

    链表 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的. 链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两 ...

  2. mysql group by语句流程是怎么样的

    group by流程是怎么样的 注意点: select id%10 as m, count(*) as c from t1 group by m; group by是用于对数据进行分组,我们排序用到了 ...

  3. JavaScript05

    显示和隐藏 元素的显示和隐藏 元素display属性可控制元素的显示和隐藏,先获取元素对象,再通过点语法调用style对象中的display属性 语法格式: 元素.style.display='non ...

  4. JAVA String、StringBuffer、StringBuilder类解读

    JAVA String.StringBuffer.StringBuilder类解读 字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作 ...

  5. 【UE4 设计模式】外观模式 Facade Pattern

    概述 描述 外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用.外观模式又称为门面模式,它是一 ...

  6. HttpClient使用GET方式通过代理服务器读取页面的例子

    import java.io.BufferedReader;import java.io.InputStreamReader;import org.apache.http.HttpEntity;imp ...

  7. 北航OO第三单元总结

    JML基础梳理及工具链 JML的全称是Java Modeling language,即Java建模语言.JML是一种行为接口规格.它为严格的程序设计提供了一套行之有效的方法.通过JML不仅可以基于规格 ...

  8. OO课第三单元总结

    一.梳理JML语言的理论基础 (1)理论基础 JMl的出现很大程度上一为了行为接口的规范化,用这种语言来指定特定模块的特定功能.JML的核心部分分为三个部分:前置条件(requires).后置条件(e ...

  9. OO第三次博客作业--第三单元总结

    一.JML 语言的理论基础及应用工具链 JML 是一种行为接口规格语言,提供了对方法和类型的规格定义手段.通过 JML 和其支持工具,不仅可以基于规格自动构造测试用例,并整合了 SMT Solver ...

  10. 用Python画如此漂亮的专业插图 ?简直So easy!

    本文整理自知乎问答,仅用于学术分享,著作权归作者所有.如有侵权,请联系我删文处理.多多转发,多多学习! 方法一 强烈推荐 Python 的绘图模块 matplotlib: python plottin ...