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 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2720580.html