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

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>
            在线成人h网| 99视频有精品| 久久综合一区| 久久久久看片| 亚洲成人在线视频网站| 免费不卡欧美自拍视频| 老司机午夜精品视频| 在线观看国产成人av片| 欧美国产高潮xxxx1819| 免费在线观看一区二区| 亚洲精品一区在线观看| 日韩亚洲精品在线| 国产欧美一区二区精品性| 久久最新视频| 欧美国产91| 亚洲女女女同性video| 午夜免费久久久久| 伊人色综合久久天天五月婷| 欧美国产综合视频| 欧美日韩一区二区在线观看| 小黄鸭精品密入口导航| 麻豆精品在线观看| 亚洲午夜一区| 久久躁日日躁aaaaxxxx| 亚洲午夜精品一区二区三区他趣| 亚洲欧美在线磁力| 亚洲第一黄网| 亚洲一区二区3| 亚洲国产天堂久久综合网| 亚洲精选91| 狠狠v欧美v日韩v亚洲ⅴ| 亚洲精品影视| 一区二区三区在线免费观看| 亚洲欧洲精品一区二区三区不卡| 国产精品美女久久久久aⅴ国产馆| 久久久91精品国产一区二区精品| 欧美黑人多人双交| 久久av免费一区| 欧美日韩成人在线| 免费一级欧美片在线观看| 欧美性大战xxxxx久久久| 欧美成人精品激情在线观看| 国产精品视频一区二区三区| 亚洲国产一区二区视频| 国产一区二区三区四区五区美女| 亚洲人成啪啪网站| 在线观看日韩精品| 性色av一区二区怡红| 亚洲视频精品在线| 欧美激情四色 | 伊人精品成人久久综合软件| 亚洲精品国产精品乱码不99 | 欧美国产日本| 暖暖成人免费视频| 国产亚洲成人一区| 亚洲午夜在线视频| 亚洲午夜精品17c| 欧美精品国产精品日韩精品| 快射av在线播放一区| 国产日本欧美在线观看| 亚洲午夜久久久久久久久电影院 | 蜜臀91精品一区二区三区| 国产精品羞羞答答xxdd| aa级大片欧美三级| 一区二区不卡在线视频 午夜欧美不卡在 | 午夜精品久久久久久久| 亚洲欧美电影院| 欧美视频日韩| 一本色道久久99精品综合| aa级大片欧美三级| 欧美日韩一区精品| 一区二区av| 午夜精品福利电影| 国产精品―色哟哟| 性做久久久久久久久| 久久精选视频| 在线观看久久av| 久久美女性网| 亚洲国产成人精品久久久国产成人一区 | 亚洲一区二区免费| 久久se精品一区二区| 好男人免费精品视频| 久久裸体艺术| 亚洲激情欧美| 午夜精品久久久久久久99樱桃 | 欧美日韩中文字幕在线| 亚洲激情在线播放| 亚洲欧美日韩一区| 影音先锋日韩资源| 欧美高清视频免费观看| 一区二区三区视频在线 | 亚洲日本电影| 欧美调教视频| 欧美在线一二三区| 欧美国产日韩视频| 亚洲深夜激情| 国产一区二区日韩| 欧美aⅴ一区二区三区视频| 日韩一区二区精品在线观看| 欧美伊人久久久久久久久影院 | 欧美日韩综合| 久久精品二区三区| 亚洲区一区二| 久久久久久久性| 亚洲精品影院在线观看| 国产模特精品视频久久久久| 老司机免费视频久久| 这里只有视频精品| 欧美大片在线观看一区| 亚洲中午字幕| 亚洲国产视频一区二区| 国产精品婷婷午夜在线观看| 麻豆成人综合网| 欧美一区二区三区视频免费| 亚洲第一区在线观看| 久久国产精品色婷婷| 亚洲免费精彩视频| 国产综合久久久久久鬼色| 欧美日韩精品免费看| 久久久久免费观看| 亚洲一区二区网站| 亚洲精品小视频| 欧美成人69av| 久久久天天操| 亚洲欧美在线aaa| 亚洲另类自拍| 亚洲国产裸拍裸体视频在线观看乱了| 国产精品区一区| 欧美片第一页| 欧美福利视频| 欧美国产国产综合| 麻豆精品在线观看| 久久久噜噜噜久久久| 欧美一区二区三区免费观看| 亚洲视频在线视频| 亚洲免费精彩视频| 亚洲国产精品激情在线观看| 久久只有精品| 久久网站热最新地址| 久久精品亚洲一区| 欧美一区二区三区在| 欧美一级专区| 午夜精品一区二区三区电影天堂| 亚洲视频在线播放| 亚洲影音先锋| 亚洲在线观看免费| 亚洲免费在线观看视频| 亚洲专区国产精品| 欧美一级理论片| 久久久91精品国产一区二区精品| 欧美综合第一页| 久久综合电影| 欧美成人国产一区二区| 亚洲电影成人| 亚洲精品久久久久久久久久久| 91久久久久久| 亚洲免费精品| 亚洲免费综合| 久久久久网址| 欧美凹凸一区二区三区视频| 欧美大片在线看| 欧美日韩在线大尺度| 国产精品区二区三区日本| 国产欧美一级| 亚洲国产精品一区二区第一页| 亚洲国产日韩一区二区| 亚洲美女电影在线| 欧美一区二区精品| 玖玖玖国产精品| 91久久亚洲| 中日韩午夜理伦电影免费| 香蕉尹人综合在线观看| 久久婷婷久久一区二区三区| 99国产精品一区| 欧美亚洲三区| 欧美二区视频| 国产女人aaa级久久久级| 激情小说另类小说亚洲欧美| 亚洲毛片在线观看.| 欧美一区二区三区的| 欧美国产精品一区| 中文日韩在线| 美日韩在线观看| 国产精品私拍pans大尺度在线| 伊人春色精品| 欧美一区二区| 亚洲国产精品国自产拍av秋霞| 亚洲综合第一| 欧美日韩国产在线| 狠狠色丁香久久综合频道| 一区二区三区不卡视频在线观看 | 中文欧美字幕免费| 久久免费视频网站| 亚洲午夜成aⅴ人片| 免费短视频成人日韩| 国产精品免费看片| 亚洲免费大片| 欧美高清在线观看| 久久av最新网址| 国产精品欧美久久|