题意:给定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; }