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

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 閱讀(1018) 評論(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>
            亚洲人成在线播放网站岛国| 91久久香蕉国产日韩欧美9色| 国产精品久久久久99| 久久国产精品色婷婷| 欧美在线www| 久久久久久日产精品| 老司机精品久久| 欧美极品aⅴ影院| 国产精品国产三级国产专播精品人 | 国产亚洲视频在线| 含羞草久久爱69一区| 亚洲欧洲美洲综合色网| 亚洲一区二区精品在线观看| 久久精品人人爽| 亚洲人成高清| 久久国产精品一区二区| 欧美精品日韩三级| 黄色成人免费观看| 亚洲五月六月| 久久伊人精品天天| 一本色道久久加勒比88综合| 久久久久久久综合色一本| 欧美日韩成人综合| 在线观看中文字幕亚洲| 性做久久久久久| 亚洲人成人一区二区三区| 亚洲欧美日韩国产一区| 欧美精品综合| 在线观看日韩www视频免费| 亚洲影院在线观看| 欧美18av| 欧美不卡三区| 欧美在线国产| 欧美aⅴ99久久黑人专区| 欧美有码视频| 亚洲欧美色一区| 欧美大片免费观看| 亚洲尤物影院| 欧美激情麻豆| 狠狠色丁香久久婷婷综合_中| 一区二区三欧美| 欧美国产综合一区二区| 亚洲欧美日韩精品久久| 欧美视频一区二区三区在线观看| 亚洲三级免费电影| 免费成人性网站| 久久精品2019中文字幕| 国产精品影片在线观看| 午夜精品视频| 亚洲亚洲精品在线观看 | 久久精品二区三区| 一本色道久久综合亚洲精品小说| 美女精品在线观看| 精品成人一区二区三区| 久久免费视频在线观看| 欧美一级理论性理论a| 国产日韩欧美麻豆| 久久成人精品视频| 亚洲欧美日韩精品| 国产午夜久久| 久久久国产精品一区二区三区| 午夜在线成人av| 国产在线麻豆精品观看| 久久成人免费网| 欧美一区二区网站| 伊人久久噜噜噜躁狠狠躁| 蜜臀va亚洲va欧美va天堂| 久久亚洲不卡| 亚洲日本成人| 一二三四社区欧美黄| 国产精品少妇自拍| 久久综合久久久| 欧美福利视频在线观看| 制服丝袜激情欧洲亚洲| 亚洲午夜国产成人av电影男同| 国产精品视频一二三| 久色婷婷小香蕉久久| 欧美激情一区二区三级高清视频 | 久久久久久久久综合| 1000部国产精品成人观看 | 性色av一区二区怡红| 国内精品免费午夜毛片| 欧美电影在线观看完整版| 亚洲激情视频网站| 欧美破处大片在线视频| 亚洲宅男天堂在线观看无病毒| 久久亚洲精品一区| 亚洲国产日韩欧美在线图片| 亚洲视频网站在线观看| 欧美性淫爽ww久久久久无| 亚洲一区在线直播| 免费高清在线视频一区·| 亚洲看片网站| 国产精品久久久久一区二区三区共 | 亚洲欧美成人网| 国产亚洲一区精品| 日韩视频专区| 99视频有精品| 亚洲深夜激情| 国产午夜精品美女视频明星a级 | 亚洲精品三级| 黄色国产精品| 一区二区三区欧美视频| 黄色精品免费| 亚洲欧美精品在线观看| 亚洲精品在线一区二区| 亚洲欧美日韩系列| 一区二区欧美日韩视频| 久久亚洲午夜电影| 欧美中文在线观看国产| 欧美日韩精品在线| 亚洲福利在线看| 国产一区二区三区四区hd| 一本一本a久久| 亚洲免费激情| 久久久精品一区| 欧美亚洲三区| 国产精品成人在线| 亚洲靠逼com| 日韩午夜免费| 免费观看国产成人| 久久午夜色播影院免费高清| 国产欧美二区| 亚洲欧美电影院| 午夜电影亚洲| 国产精品网站一区| 一区二区三区高清| 在线亚洲精品| 欧美日韩亚洲三区| 最新日韩欧美| 99在线热播精品免费| 欧美黑人多人双交| 亚洲成色最大综合在线| 欧美日本一道本在线视频| 国产午夜一区二区三区| 久久婷婷综合激情| 国内精品伊人久久久久av影院| 亚洲性视频网址| 亚洲欧美亚洲| 国产精品午夜春色av| 亚洲专区一区| 久久久精品五月天| 影音先锋亚洲一区| 免费日韩视频| 亚洲精品社区| 午夜亚洲性色视频| 国产精品美女999| 午夜电影亚洲| 美乳少妇欧美精品| 亚洲美女在线观看| 国产精品成人观看视频国产奇米| 国产精品99久久不卡二区| 一本色道久久综合亚洲精品不卡| 欧美精品激情在线| 正在播放亚洲一区| 欧美一区二区三区播放老司机| 国产一区再线| 嫩模写真一区二区三区三州| 亚洲精品一区二区三区99| 亚洲欧美综合精品久久成人| 韩国v欧美v日本v亚洲v| 牛牛精品成人免费视频| 宅男噜噜噜66一区二区| 久久最新视频| 亚洲一区免费观看| 一区二区三区视频免费在线观看| 欧美1区视频| 欧美日本韩国一区| 9l国产精品久久久久麻豆| 亚洲六月丁香色婷婷综合久久| 欧美日韩中文精品| 久久综合九九| 欧美视频不卡中文| 欧美尤物一区| 欧美另类久久久品| 久久成人免费网| 欧美顶级少妇做爰| 欧美一区二区三区视频免费播放 | 久久综合伊人77777| 国产精品99久久久久久有的能看| 久久国产免费看| 亚洲日韩第九十九页| 夜夜嗨一区二区| 久久久精品一区| 在线视频精品| 亚洲国产精品成人va在线观看| 欧美色网在线| 久久综合九色综合久99| 亚洲视频免费看| 亚洲综合精品一区二区| 久久国产精品久久国产精品| 亚洲人成在线免费观看| 国产视频亚洲精品| 欧美精品综合| 麻豆乱码国产一区二区三区| 亚洲欧美视频在线| 一区二区精品在线| 亚洲九九精品| 亚洲国产成人在线| 麻豆精品视频|