poj 2201 笛卡尔树

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


你可能感兴趣的:(poj 2201 笛卡尔树)