码迷,mamicode.com
首页 > 其他好文 > 详细

笛卡尔树

时间:2019-03-29 13:21:09      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:treap   mil   ace   答案   区间   ogr   for   图片   algorithm   

笛卡尔树的节点具有两个属性:键值与权值。

中序遍历每个节点,则其键值递增。任意一个父亲的权值都一定大于(小于)其儿子的权值。

由此可知,笛卡尔树的键值具有二叉搜索树的性质,权值具有堆的性质。Treap就是实现了一棵笛卡尔树。

笛卡尔树一般是根据序列建立的,一般以序列下标为键值,序列中的数为权值。

它的建立与虚树相似,从左到右将序列中的点依次插入树中,维护树的右链即可轻松实现。

一般来说,笛卡尔树中的一个点代表的是一段位置,这段位置就是中序遍历这个点的子树得到的那段连续区间(下面叫它管辖范围),在DP中也可能代表当前这个位置所在的极大矩形。

下面是几个简单的应用:

 

1.[POJ2559]Largest Rectangle in a Histogram

给一张图求出其中最大的矩形。

这是一道单调栈模板题,考虑笛卡尔树的做法。

注意到答案就是每个点的管辖范围宽度乘上这个点的权值h[]。

技术图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 typedef long long ll;
 5 using namespace std;
 6 
 7 const int N=100010;
 8 ll ans;
 9 int n,top,rt,a[N],w[N],stk[N],son[N][2];
10 
11 void dfs(int x,int L,int R){
12     w[x]=R-L+1; ans=max(ans,1ll*w[x]*a[x]);
13     if (son[x][0]) dfs(son[x][0],L,x-1);
14     if (son[x][1]) dfs(son[x][1],x+1,R);
15 }
16 
17 int main(){
18     freopen("poj2559.in","r",stdin);
19     freopen("poj2559.out","w",stdout);
20     while (scanf("%d",&n),n){
21         rep(i,1,n) scanf("%d",&a[i]);
22         top=0;
23         rep(i,1,n) son[i][0]=son[i][1]=0;
24         rep(i,1,n){
25             while (top && a[stk[top]]>a[i]) son[i][0]=stk[top--];
26             if (top) son[stk[top]][1]=i;
27             stk[++top]=i;
28         }
29         rt=stk[1]; ans=0; dfs(rt,1,n); printf("%lld\n",ans);
30     }
31     return 0;
32 }
POJ2559

 

笛卡尔树

标签:treap   mil   ace   答案   区间   ogr   for   图片   algorithm   

原文地址:https://www.cnblogs.com/HocRiser/p/10620518.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!