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

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 閱讀(1024) 評論(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>
            欧美大片免费| 国产精品www网站| 在线国产日韩| 欧美激情91| 欧美大片在线看| 亚洲视频碰碰| 亚洲一区二区三区涩| 国产精品视频大全| 狼人天天伊人久久| 欧美国产精品v| 亚洲一区在线播放| 欧美一区2区视频在线观看| 一区免费在线| 亚洲精品黄色| 国产精品欧美日韩| 欧美bbbxxxxx| 国产精品护士白丝一区av| 久久久99精品免费观看不卡| 免费日本视频一区| 午夜精品福利在线观看| 久久久久国产精品一区| 日韩午夜在线观看视频| 香蕉久久a毛片| 亚洲精品小视频| 性欧美videos另类喷潮| 亚洲精品一区二区三区99| 午夜精品久久99蜜桃的功能介绍| 在线观看日韩精品| 99re在线精品| 一区视频在线| 亚洲综合清纯丝袜自拍| 亚洲欧洲日韩女同| 欧美在线一级va免费观看| 日韩视频精品在线观看| 欧美一区二区三区久久精品茉莉花| 亚洲乱码国产乱码精品精可以看| 亚洲欧美在线一区| 亚洲一区国产| 欧美成人自拍| 蜜臀av一级做a爰片久久| 国产精品影音先锋| 一本色道久久综合亚洲精品不| 国产一区二区三区在线观看免费| 一区二区三区偷拍| 亚洲理伦在线| 麻豆精品精品国产自在97香蕉| 久久国产精品亚洲77777| 欧美日韩精品综合在线| 亚洲国产精品尤物yw在线观看| 激情综合网激情| 欧美亚洲视频在线看网址| 午夜国产不卡在线观看视频| 欧美国产先锋| 91久久综合亚洲鲁鲁五月天| 136国产福利精品导航网址| 午夜激情亚洲| 午夜欧美视频| 国产精品亚洲成人| 亚洲一区日韩| 性视频1819p久久| 国产精品乱码| 亚洲女同精品视频| 欧美一区二区三区男人的天堂| 国产精品国产亚洲精品看不卡15| 一本色道久久99精品综合| 一本色道精品久久一区二区三区 | 美女视频黄a大片欧美| 国产精品免费在线 | 欧美国产精品中文字幕| 激情自拍一区| 媚黑女一区二区| 91久久精品美女高潮| 亚洲精品中文字幕在线| 欧美精选午夜久久久乱码6080| 亚洲福利视频一区| 99视频精品全国免费| 欧美日韩在线直播| 亚洲欧美一区二区精品久久久| 欧美在线观看视频一区二区| 激情懂色av一区av二区av| 久久久综合免费视频| 欧美激情网友自拍| 亚洲一区二区三区高清不卡| 国产欧美日韩精品在线| 久久久久久九九九九| 亚洲国产精品成人| 亚洲综合电影| 精品51国产黑色丝袜高跟鞋| 麻豆精品国产91久久久久久| 亚洲精品字幕| 久久国产精品久久久久久电车| 极品尤物一区二区三区| 欧美激情2020午夜免费观看| 亚洲视频在线看| 牛牛精品成人免费视频| 一区二区高清在线| 国产自产女人91一区在线观看| 麻豆精品在线视频| 亚洲网站视频| 欧美国产激情二区三区| 亚洲欧美在线免费观看| 伊人久久成人| 国产精品久久久久影院亚瑟| 久久精品国产欧美亚洲人人爽| 91久久精品国产| 欧美一区观看| 亚洲作爱视频| 狠狠色狠狠色综合日日tαg| 欧美日韩第一区| 麻豆国产va免费精品高清在线| 亚洲一区在线视频| 91久久一区二区| 久久久无码精品亚洲日韩按摩| 一区二区三区精品视频在线观看| 国内成+人亚洲| 欧美特黄一级| 欧美精品在线观看91| 久久久久成人精品| 中文在线资源观看网站视频免费不卡| 美女露胸一区二区三区| 午夜精品久久久久久久久| 日韩亚洲视频| 亚洲精品视频在线观看免费| 国产一区二区三区四区三区四| 国产精品第一页第二页第三页| 欧美大片免费久久精品三p | 亚洲人成网站精品片在线观看| 久久国产毛片| 午夜精品偷拍| 亚洲一区二区在线免费观看| 日韩手机在线导航| 91久久精品国产91性色| 在线观看日韩av先锋影音电影院| 国产欧美视频一区二区| 国产精品美女久久福利网站| 欧美午夜精品伦理| 欧美日韩免费视频| 欧美日韩成人一区二区三区| 欧美成人一区二区三区片免费| 开心色5月久久精品| 久久婷婷国产综合国色天香| 欧美专区一区二区三区| 午夜视频在线观看一区二区三区 | 久久久久久久久久看片| 久久成人综合视频| 久久精品国产免费观看| 欧美一级大片在线观看| 欧美怡红院视频| 久久久www成人免费毛片麻豆| 欧美一区二区三区在线免费观看| 亚洲欧美一区二区激情| 欧美一区=区| 久久精品日韩欧美| 久热精品视频在线免费观看| 蜜臀av国产精品久久久久| 欧美电影电视剧在线观看| 亚洲国语精品自产拍在线观看| 亚洲国产婷婷综合在线精品 | 亚洲精品欧美日韩专区| 亚洲精品综合久久中文字幕| 一本色道久久综合亚洲91| 亚洲永久免费精品| 久久精品一区二区| 欧美xart系列高清| 欧美日韩亚洲综合一区| 国产精品在线看| 在线看片成人| 亚洲视频电影图片偷拍一区| 久久不射中文字幕| 欧美va亚洲va香蕉在线| 亚洲三级毛片| 新片速递亚洲合集欧美合集| 久久精品视频在线免费观看| 欧美好骚综合网| 国产欧美在线看| 亚洲人成网站在线观看播放| 亚洲欧美综合网| 女女同性精品视频| 亚洲一卡久久| 欧美国产成人精品| 国产亚洲一区在线| 99精品视频免费| 久久久综合免费视频| 亚洲精品1区| 久久精品在线视频| 欧美新色视频| 91久久国产综合久久| 性做久久久久久| 亚洲区一区二区三区| 欧美一级视频一区二区| 欧美日韩成人在线| 亚洲第一天堂无码专区| 亚洲欧美另类在线观看| 亚洲国产精品一区二区www| 亚洲欧美国产精品桃花| 欧美日韩a区| 亚洲精品欧美在线| 免费在线亚洲欧美| 香蕉久久夜色精品国产| 欧美日韩精品免费观看视一区二区 |