poj1785

1.理解了rmq的st算法。就是将每个大区间用刚好大于其长度一半的2^x的大小来将其分割为两个有重叠区间求解。即s~t被分为s~s + 2^x 和 t - 2^x + 1 ~t。吉大的第一个st是错误的。

2.学会了笛卡尔树,即一个满足堆的大小性质的二叉搜索树,但不一定是完全二叉树。这是将rmq转为lca的关键。

3.scanf的用法,%*[ ],表示越过[ ]中的字符,%[a-z]表示读入字符串,直到遇到不是a-z中的字符为止。%[^a]表示读入字符串直到遇到字符a为止,但a并没有被读入。

题意:给出一些节点,每个节点有两个值,lable和priority(都是唯一的),要求构成一个笛卡尔树,按lable是二叉排序树,按priority是大根堆(不一定完全二叉树)。输出括号表示。

分析:先把节点按lable排序,从小到大依次插入,这样每次插入的节点就要插到排序二叉树的最右边,首先要沿着右儿子找到最右边的节点(再无右儿子),然后分两种情况,最右节点的priority和当前插入节点的priority比较,若大于则直接将当前插入节点接到其右子树。否则让当前插入节点取代最右节点位置并将原最右节点及其子树接到当前插入节点的左子树。

View Code
#include < iostream >
#include
< cstdio >
#include
< cstdlib >
#include
< cstring >
#include
< algorithm >
using namespace std;

#define maxn 100005

struct Node
{
char c[ 100 ];
int v;
int l, r, fa;
} tree[maxn];

int n;

bool operator < ( const Node & a, const Node & b)
{
return strcmp(a.c, b.c) < 0 ;
}

void input()
{
for ( int i = 1 ; i <= n; i ++ )
scanf(
" %*[ ]%[^/]/%d " , tree[i].c, & tree[i].v);
}

void ins( int i)
{
int j = i - 1 ;

while (tree[j].v < tree[i].v)
j
= tree[j].fa;
tree[i].l
= tree[j].r;
tree[tree[i].l].fa
= i;
tree[j].r
= i;
tree[i].fa
= j;
}

void dfs( int i)
{
if ( ! i)
return ;
printf(
" ( " );
dfs(tree[i].l);
printf(
" %s/%d " , tree[i].c, tree[i].v);
dfs(tree[i].r);
printf(
" ) " );
}

int main()
{
// freopen("t.txt", "r", stdin);
while (scanf( " %d " , & n), n)
{
input();
tree[
0 ].l = tree[ 0 ].r = tree[ 0 ].fa = 0 ;
tree[
0 ].v = 0x3f3f3f3f ;
sort(tree
+ 1 , tree + n + 1 );
for ( int i = 1 ; i <= n; i ++ )
{
tree[i].l
= tree[i].r = tree[i].fa = 0 ;
ins(i);
}
dfs(tree[
0 ].r);
printf(
" \n " );
}
return 0 ;
}

你可能感兴趣的:(poj)