题意:给定n个二元组(ai,bi),构造笛卡尔树。按a元素为二叉排序树,按b元素为小顶堆。
思路:用栈当然可以,此处用了rmq来做。另外需要注意笛卡尔树和treap的区别:Treap与笛卡尔树在结构上是相同的,只是两者的应用不同。treap的value是随机值,是为了使树更加平衡引进的,而笛卡尔树的value是一个确定的值。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define N 50005
struct node{
int x,y,id;
int l,r,f;
}p[N];
int n,dp[N][20];
int cmp(const void* a,const void* b){
return (*(struct node*)a).x - (*(struct node*)b).x;
}
void st(){
int i,j,k = log((double)(n+1))/log(2.);
for(i = 1;i<=n;i++)
dp[i][0] = i;
for(j = 1;j<=k;j++)
for(i = 1;i+(1<<j)-1<=n;i++){
if(p[dp[i][j-1]].y < p[dp[i+(1<<(j-1))][j-1]].y)
dp[i][j] = dp[i][j-1];
else
dp[i][j] = dp[i+(1<<(j-1))][j-1];
}
}
int query(int a,int b){
int k = log((double)(b-a+1))/log(2.);
if(p[dp[a][k]].y < p[dp[b-(1<<k)+1][k]].y)
return dp[a][k];
return dp[b-(1<<k)+1][k];
}
int cartesian(int a,int b,int fa){
int i,j,k;
if(a>b)
return 0;
k = query(a,b);
p[p[k].id].f = p[fa].id;
i = cartesian(a, k-1,k);
p[p[k].id].l = p[i].id;
j = cartesian(k+1, b,k);
p[p[k].id].r = p[j].id;
return k;
}
int main(){
int i;
scanf("%d",&n);
for(i = 1;i<=n;i++){
scanf("%d %d",&p[i].x,&p[i].y);
p[i].id = i;
}
qsort(p+1,n,sizeof(struct node),cmp);
st();
printf("YES\n");
cartesian(1,n,0);
for(i = 1;i<=n;i++)
printf("%d %d %d\n",p[i].f,p[i].l,p[i].r);
return 0;
}