POJ 2201 笛卡尔树+RMQ

题意:

题目大意:

让你构造一棵笛卡尔树。

笛卡尔树的节点含有2个值,1个key,一个value,其中key是主键,value是辅键。一棵笛卡尔树就是:key升序,value升序或者降序。类似堆。

判断能否构成。(PS:此题保证数据相异,必然能够成)

 

思路:
第一次做,参考的别人的,不过这个模板好像写的有点别扭。。

自我感觉思路比较清晰的模板见我的下一篇文章:http://www.cnblogs.com/proverbs/archive/2012/10/11/2720592.html

 

View Code
 1 #include <cstdio>

 2 #include <cstring>

 3 #include <cstdlib>

 4 #include <iostream>

 5 #include <algorithm>

 6 

 7 #define N 200000

 8 

 9 using namespace std;

10 

11 struct PO

12 {

13     int a,w,id;

14 }po[N];

15 

16 struct TREE

17 {

18     int u,l,r;

19 }tr[N*2];

20 

21 int pn[N][20],lg[N],n;

22 

23 inline bool cmp(const PO &a,const PO &b)

24 {

25     return a.a<b.a;

26 }

27 

28 inline int jmin(int x,int y)

29 {

30     if(po[x].w>po[y].w) return y;

31     else return x;

32 }

33 

34 inline int askmin(int l,int r)

35 {

36     int k=lg[r-l+1];

37     return jmin(pn[l][k],pn[r-(1<<k)+1][k]);

38 }

39 

40 void init_rmq()

41 {

42     for(int i=1;i<=n;i++) pn[i][0]=i;

43     for(int j=1;(1<<j)<=n;j++)

44         for(int i=1;i+(1<<j)-1<=n;i++)

45             pn[i][j]=jmin(pn[i][j-1],pn[i+(1<<(j-1))][j-1]);

46 }

47 

48 void read()

49 {

50     for(int i=1;i<=n;i++)

51     {

52         scanf("%d%d",&po[i].a,&po[i].w);

53         po[i].id=i;

54     }

55     sort(po+1,po+1+n,cmp);

56     init_rmq();

57 }

58 

59 int create(int u,int l,int r)

60 {

61     if(l>r) return 0;

62     int pos=askmin(l,r);

63     int sta=po[pos].id;

64     tr[sta].u=u;

65     tr[sta].l=create(sta,l,pos-1);

66     tr[sta].r=create(sta,pos+1,r);

67     return sta;

68 }

69 

70 void go()

71 {

72     create(0,1,n);

73     puts("YES");

74     for(int i=1;i<=n;i++)

75         printf("%d %d %d\n",tr[i].u,tr[i].l,tr[i].r);

76 }

77 

78 int main()

79 {

80     for(int i=1;i<N;i++)

81         lg[i]=(i>>lg[i-1]+1)?lg[i-1]+1:lg[i-1];

82     while(scanf("%d",&n)!=EOF)

83     {

84         read();

85         go();

86     }

87     return 0;

88 }

 

 

你可能感兴趣的:(poj)