青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

QuXiao

每天進步一點點!

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  50 隨筆 :: 0 文章 :: 27 評論 :: 0 Trackbacks
題目來源:

                PKU 2201 Cartesian Tree

分類:

                RMQ

原文:

 

Cartesian Tree

Time Limit: 10000MS


Memory Limit: 65536K

Total Submissions: 1196


Accepted: 423

Case Time Limit: 2000MS

Description

Let us consider a special type of a binary search tree, called a cartesian tree. Recall that a binary search tree is a rooted ordered binary tree, such that for its every node x the following condition is satisfied: each node in its left subtree has the key less then the key of x, and each node in its right subtree has the key greater then the key of x.
That is, if we denote left subtree of the node x by L(x), its right subtree by R(x) and its key by kx then for each node x we have

  • if y L(x) then ky < kx
  • if z R(x) then kz > kx


The binary search tree is called cartesian if its every node x in addition to the main key kx also has an auxiliary key that we will denote by ax, and for these keys the heap condition is satisfied, that is

  • if y is the parent of x then ay < ax


Thus a cartesian tree is a binary rooted ordered tree, such that each of its nodes has a pair of two keys (k, a) and three conditions described are satisfied.
Given a set of pairs, construct a cartesian tree out of them, or detect that it is not possible.

Input

The first line of the input file contains an integer number N -- the number of pairs you should build cartesian tree out of (1 <= N <= 50 000). The following N lines contain two numbers each -- given pairs (ki, ai). For each pair |ki|, |ai| <= 30 000. All main keys and all auxiliary keys are different, i.e. ki != kj and ai != aj for each i != j.

Output

On the first line of the output file print YES if it is possible to build a cartesian tree out of given pairs or NO if it is not. If the answer is positive, on the following N lines output the tree. Let nodes be numbered from 1 to N corresponding to pairs they contain as they are given in the input file. For each node output three numbers -- its parent, its left child and its right child. If the node has no parent or no corresponding child, output 0 instead.
The input ensure these is only one possible tree.

Sample Input

7

5 4

2 2

3 9

0 5

1 3

6 6

4 11

Sample Output

YES

2 3 6

0 5 1

1 0 7

5 0 0

2 4 0

1 0 0

3 0 0

Source

Northeastern Europe 2002, Northern Subregion

 

 

 

 

中文描述:

                有一種二叉樹,叫笛卡爾樹,樹的節點有兩個值:kak值滿足二叉排序樹的性質,a值滿足最小堆的性質。即如果某個根節點root有兩個子節點leftright,那么left.k < root.k < right.k,且root.a < left.aroot.a < right.a。給你N(1 <= N <= 50 000)個節點,問你是否可以構造出一棵笛卡爾樹。

 

題目分析與算法模型

                一開始,自己是想根據最小堆的性質,擁有最小a值的那個節點一定是樹的根,接著再找兩個次小a值的節點,它們必然是根的兩個子節點,再根據k值決定節點是左兒子還是右兒子,然后再以此類推…………,但是在下一層就不對了。因為并不是樹的下一層節點的a值一定比上一層節點的a值大(它們不一定在同一棵子樹)。

                可以換一個思維,把注意力放在k值上。要知道,如果對一顆二叉排序樹進行前序搜索,k值是從小到大排序的。如果某個節點是根,那么它左邊的節點就構成左子樹,它右邊的節點就構成右子樹。現在,那個根節點是哪一個?就是那個a值最小的節點!所以,我們可以對k值進行排序,現在整個區間內找到a值最小的節點,他就是根。接著再在左邊和右邊的區間內各找一個a值最小的節點,看它們的節點的k值與根節點的k值是否滿足二叉排序樹的性質,如果滿足,就用相同的方法在左、右區間遞歸建立子樹;如果不滿足,表示無法構成笛卡爾樹。


                接下來的問題就是,如何在一區間里找到最小的a值?最容易想到的就是O(n)復雜度的線性查找,但在此題中,N最大為50000,并且當在一個較大區間內查找到一個最值后,又要在一個較小的區間內查找另一個最值,一些節點被查找了多次,造成時間的浪費。那么,怎么高效的進行多次的區間查詢呢?RMQ是一個不錯的解決方法。大致思想是:先對區間內的數進行預處理,計算出從某一下標開始的某一特定長度的最值。當查找某一區間的最值時,就可以把這個區間分解成一個或兩個已預先算出最值得區間,這樣就可以用O(1)的復雜度算出最值了。(具體講解請查閱相關資料)

 

代碼:

#include <iostream>

#include <cmath>

#include <algorithm>

using namespace std;

 

const int MAX = 50005;

 

struct Node

{

          int index;

          int k, a;

          int parent, left, right;

};

 

Node node[MAX];

int left, right;

int f[MAX][16];                  //f[i][j] is the index of the min a from i

                                 //to i + 2^j - 1

int n;

 

bool cmpByK (Node n1, Node n2)

{

          return ( n1.k < n2.k );

}

 

bool cmpByIndex (Node n1, Node n2)

{

          return ( n1.index < n2.index );

}

 

void Input ()

{

          int i;

          scanf("%d", &n);

          for (i=0; i<n; i++)

          {

                  scanf("%d%d", &node[i].k, &node[i].a);

                  node[i].index = i + 1;

          }

}

 

int Max (int a, int b)

{

          return ( a>b?a:b );

}

 

 

int Min (int a, int b)

{

          return ( a<b?a:b );

}

 

 

void Initial ()

{

          int i, k, m;

          sort(node, node+n, cmpByK);

 

 

          //RMQ

          for (i=0; i<n; i++)

                  f[i][0] = i;

 

          m = floor(log(double(n)) / log(double(2))) + 1;

          for (k=1; k<m; k++)

          {

                  for (i=0; i<n; i++)

                  {

                         f[i][k] = f[i][k-1];

                         if ( i + (1<<(k-1)) < n )

                         {

                                 if ( node[f[i][k-1]].a > node[f[i + (1<<(k-1))][k-1]].a )

                                         f[i][k] = f[i + (1<<(k-1))][k-1];

                         }

                  }

          }

}

 

 

int MinAIndex (int i, int j)

{

          int k;

          k = floor( log(double(j-i+1)) / log(double(2)) );

          if (node[f[i][k]].a <= node[f[j - (1<<k) + 1][k]].a)

                  return f[i][k];

          else

                  return f[j - (1<<k) + 1][k];

}

 

bool MakeTree (int i, int j)

{

          if ( i == j )

          {

                  node[i].left = node[i].right = 0;

                  return true;

          }

          int rootIndex, leftIndex, rightIndex;

          bool check1, check2;

          rootIndex = MinAIndex(i, j);

         

          if ( rootIndex != i )

                  leftIndex = MinAIndex(i, rootIndex-1);

          if ( rootIndex != j )

                  rightIndex = MinAIndex(rootIndex+1, j);

 

          check1 = true;

          if ( rootIndex != i && node[rootIndex].k > node[leftIndex].k )

          {

                  node[rootIndex].left = node[leftIndex].index;

                  node[leftIndex].parent = node[rootIndex].index;

                  check1 = MakeTree(i, rootIndex-1);

          }

          check2 = true;

          if ( rootIndex != j && node[rootIndex].k < node[rightIndex].k )

          {

                  node[rootIndex].right = node[rightIndex].index;

                  node[rightIndex].parent = node[rootIndex].index;

                  check2 = MakeTree(rootIndex+1, j);

          }

 

          return ( check1 && check2 );

}

         

void Solve ()

{

          if ( MakeTree(0, n-1) )

          {

                  printf("YES\n");

                  sort(node, node+n, cmpByIndex);

                  for (int i=0; i<n; i++)

                  {

                         printf("%d %d %d\n", node[i].parent, node[i].left, node[i].right);

                  }

          }

          else

          {

                  printf("NO\n");

          }

}

 

int main ()

{

          Input ();

          Initial ();

          Solve ();

 

          return 0;

}

 

posted on 2008-04-25 21:27 quxiao 閱讀(1026) 評論(1)  編輯 收藏 引用 所屬分類: ACM

評論

# re: PKU 2201 Cartesian Tree[未登錄] 2009-05-12 12:20 k
笛卡爾樹在排好序的情況下有o(n)構造法  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲在线视频网站| 美日韩精品免费| 一本到高清视频免费精品| 欧美高清hd18日本| 亚洲精选一区二区| 一个色综合av| 国产精品视频区| 久久精品在线观看| 久久综合一区二区| 99视频精品免费观看| 99re6热在线精品视频播放速度| 欧美视频第二页| 久久婷婷蜜乳一本欲蜜臀| 农村妇女精品| 欧美大片免费久久精品三p | 欧美激情综合在线| 亚洲视频网站在线观看| 亚洲视频碰碰| 在线看一区二区| 亚洲精品一区二区三区婷婷月 | 国产乱子伦一区二区三区国色天香| 午夜精品久久久久久久男人的天堂| 欧美一区1区三区3区公司| 亚洲黄色尤物视频| 亚洲午夜精品在线| 亚洲国产精品999| 亚洲视频第一页| 在线观看亚洲精品视频| 一区二区三区产品免费精品久久75| 国产亚洲欧洲997久久综合| 最新国产成人在线观看| 国产九九精品视频| 亚洲激情视频在线| 黄色av成人| 在线视频你懂得一区| 亚洲第一区色| 亚洲欧美一区二区精品久久久 | 国产精品高潮呻吟久久av黑人| 欧美在线1区| 欧美精品一区二区精品网| 久久国产视频网| 欧美性大战久久久久久久| 欧美岛国在线观看| 国产手机视频精品| 日韩小视频在线观看专区| 亚洲第一色在线| 欧美在线在线| 亚欧美中日韩视频| 欧美日韩中文在线观看| 欧美激情久久久久久| 国内精品久久久久久影视8 | 麻豆国产va免费精品高清在线| 国产精品vvv| 亚洲精品视频在线观看免费| 怡红院精品视频| 久久激情视频| 久久精品av麻豆的观看方式| 国产精品高潮呻吟久久av无限| 亚洲欧洲精品一区二区| 亚洲国产mv| 久久先锋影音av| 米奇777超碰欧美日韩亚洲| 国产亚洲欧美一区在线观看| 亚洲一区二区综合| 午夜精品剧场| 国产日韩一区欧美| 午夜在线电影亚洲一区| 久久av二区| 国产视频自拍一区| 欧美在线三区| 麻豆成人在线观看| 亚洲电影专区| 欧美激情综合网| 日韩亚洲精品电影| 亚洲综合视频1区| 国产精品美女诱惑| 性伦欧美刺激片在线观看| 欧美一区二区三区视频在线| 国产毛片精品国产一区二区三区| 亚洲一区二区黄| 久久久99爱| 亚洲高清久久| 欧美日韩国产综合网| 亚洲一区二区三区乱码aⅴ蜜桃女| 亚洲欧美日韩在线综合| 国产亚洲精品bt天堂精选| 久久精品一区蜜桃臀影院| 麻豆精品视频| 一本一本久久| 国产精品无码专区在线观看| 久久国产精品久久久久久电车| 快播亚洲色图| 一区二区三区精品国产| 国产精品永久在线| 久久蜜桃香蕉精品一区二区三区| 亚洲国产99| 亚洲自拍电影| 伊伊综合在线| 国产精品爱久久久久久久| 欧美在线高清| 亚洲日本在线观看| 欧美一级视频一区二区| 亚洲福利在线看| 国产精品久久久久av| 久久亚洲不卡| 亚洲影院在线观看| 欧美国产一区视频在线观看| 亚洲欧美日韩在线播放| 亚洲国产小视频在线观看| 国产精品chinese| 久久综合色影院| 午夜久久久久久久久久一区二区| 欧美国产亚洲精品久久久8v| 午夜视黄欧洲亚洲| 99综合在线| 亚洲第一精品夜夜躁人人爽| 国产精品乱码妇女bbbb| 男女av一区三区二区色多| 亚洲欧美国产高清| 亚洲免费成人av电影| 欧美高清视频在线观看| 性伦欧美刺激片在线观看| 一区二区av在线| 亚洲第一精品夜夜躁人人爽| 国产日韩在线不卡| 国产精品萝li| 欧美午夜久久久| 欧美激情a∨在线视频播放| 久久午夜国产精品| 午夜精品久久久久久久久久久久| 亚洲精品影院| 亚洲精品一区二区三区四区高清 | 亚洲免费伊人电影在线观看av| 欧美激情一区二区三区全黄| 久久久综合免费视频| 欧美亚洲综合久久| 亚洲欧美一区二区视频| 亚洲一区二区欧美| 中文精品一区二区三区| 日韩视频二区| 日韩一级黄色大片| 日韩小视频在线观看专区| 亚洲人午夜精品免费| 最新国产成人av网站网址麻豆 | 国产精品日韩一区二区| 国产精品乱人伦一区二区| 欧美午夜不卡在线观看免费 | 亚洲一区亚洲二区| 亚洲一级特黄| 亚洲综合清纯丝袜自拍| 亚洲一区二区综合| 先锋影院在线亚洲| 久久99在线观看| 久久久久久久一区二区| 久久资源av| 欧美精选午夜久久久乱码6080| 欧美国产日韩一二三区| 欧美日韩三级一区二区| 国产精品你懂的| 国产精品综合久久久| 黑丝一区二区| 亚洲精品日韩一| 亚洲一品av免费观看| 久久xxxx精品视频| 欧美不卡高清| 亚洲精品国精品久久99热| 一区二区三区成人| 久久国产欧美| 欧美日本韩国在线| 国产目拍亚洲精品99久久精品| 国产日韩欧美亚洲| 亚洲欧洲日韩综合二区| 一二三区精品福利视频| 欧美亚洲在线| 亚洲国产日韩欧美综合久久| 亚洲最新视频在线播放| 久久国产精品毛片| 欧美日韩福利在线观看| 国产精品一区久久久久| 亚洲国产精选| 亚洲综合精品一区二区| 欧美va天堂| 国产精品99久久久久久www| 欧美一区在线视频| 欧美日韩精品系列| 韩国美女久久| 亚洲欧美日韩精品久久| 欧美风情在线| 亚洲欧美中文日韩v在线观看| 久久尤物电影视频在线观看| 国产精品日韩欧美综合| 亚洲伦理中文字幕| 久久精品亚洲一区二区三区浴池| 亚洲茄子视频| 久久综合国产精品| 国产日韩在线一区| 亚洲一区二区视频| 亚洲成色www久久网站| 久久九九精品| 中文一区在线|