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

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>
            久久精品噜噜噜成人av农村| 亚洲一区国产| 久久性天堂网| 午夜精品久久久久久99热| 欧美午夜不卡| 香蕉久久国产| 久久久久久有精品国产| 亚洲国产一区二区在线| 亚洲大片在线| 欧美激情bt| 亚洲欧美一区二区三区在线| 小处雏高清一区二区三区| 国内揄拍国内精品久久| 亚洲国产电影| 国产精品视频内| 蜜臀久久99精品久久久画质超高清| 老司机免费视频一区二区| 日韩午夜av在线| 亚洲免费在线观看| 亚洲区中文字幕| 亚洲欧美日韩精品在线| 亚洲大片精品永久免费| 一本久久精品一区二区| 国产在线精品一区二区中文| 亚洲国产网站| 黑丝一区二区三区| 一区二区三区高清不卡| 黄色日韩在线| 亚洲欧美日韩中文在线制服| 亚洲国语精品自产拍在线观看| 在线视频中文亚洲| 91久久久久久久久久久久久| 亚洲影院免费观看| 99国产精品视频免费观看一公开| 亚洲自拍电影| 宅男精品视频| 免费成人黄色片| 久久久久久久久一区二区| 欧美精品观看| 欧美激情亚洲| 激情av一区二区| 亚洲欧美日韩天堂| 亚洲一区二区在线观看视频| 欧美.www| 亚洲成人在线网| 国内自拍视频一区二区三区| 亚洲欧美国产另类| 亚洲视频自拍偷拍| 欧美精品麻豆| 亚洲精品乱码| 99riav国产精品| 欧美顶级少妇做爰| 欧美成人免费网| 亚洲电影免费观看高清完整版| 欧美一二三区在线观看| 亚洲欧美日韩国产一区二区| 欧美日韩不卡| 亚洲伦理久久| 亚洲经典一区| 男男成人高潮片免费网站| 美女在线一区二区| 玉米视频成人免费看| 久久精品九九| 欧美国产精品久久| 亚洲精品久久久久久久久久久久 | 一区二区三区免费网站| 亚洲精品在线观| 欧美激情精品久久久久久蜜臀| 欧美激情五月| 夜夜嗨av一区二区三区| 欧美激情视频一区二区三区免费 | 亚洲一本视频| 久久爱www久久做| 国内视频一区| 免费欧美视频| 亚洲美女黄色片| 亚洲一区二区三区免费观看| 国产精品久久久久三级| 亚洲欧美日韩精品在线| 久久综合中文色婷婷| 亚洲黄网站黄| 国产精品a久久久久久| 亚洲欧美日韩在线不卡| 久久综合伊人77777| 91久久在线视频| 欧美午夜在线观看| 欧美专区在线观看| 亚洲国产成人精品女人久久久| 亚洲少妇诱惑| 国产一区二区三区在线观看免费| 久久久精品2019中文字幕神马| 亚洲高清在线观看| 亚洲欧美日韩精品综合在线观看| 国模精品一区二区三区色天香| 欧美成人一区二区三区在线观看 | 欧美亚州一区二区三区| 欧美一级网站| 亚洲激情偷拍| 久久久久.com| 99日韩精品| 国产综合一区二区| 欧美视频精品一区| 久久久精品一区二区三区| 亚洲精品欧美精品| 久久欧美中文字幕| 亚洲影院高清在线| 亚洲欧洲精品一区二区| 国产精品自在线| 欧美伦理视频网站| 久久久久99| 香蕉久久一区二区不卡无毒影院| 亚洲精选在线| 欧美成人免费全部| 久久久99国产精品免费| 亚洲视频精选在线| 亚洲精品国精品久久99热一| 国产一区久久| 国产精品日韩在线| 欧美伦理视频网站| 欧美大胆人体视频| 久久一二三四| 欧美在线影院| 先锋影音网一区二区| 99视频有精品| 亚洲精品视频在线播放| 欧美 日韩 国产在线| 久久久久久久尹人综合网亚洲| 亚洲综合精品一区二区| 99国产麻豆精品| 日韩午夜高潮| 日韩一级裸体免费视频| 亚洲国产精品一区制服丝袜 | 亚洲免费大片| 最近中文字幕日韩精品 | 欧美国产日韩精品免费观看| 欧美一区二区在线观看| 亚洲无亚洲人成网站77777| 亚洲免费观看| 亚洲精品国产精品久久清纯直播| 好吊妞**欧美| 韩国在线一区| 一区二区三区在线不卡| 精品成人在线| 亚洲国产中文字幕在线观看| 亚洲国产精品第一区二区| 亚洲国产精品va| 亚洲免费久久| 一区二区三区成人| 亚洲女性喷水在线观看一区| 午夜精品福利在线| 欧美一区二区三区在线播放| 久久av一区二区三区| 久久久国产精品亚洲一区| 久久精品一二三区| 欧美高清影院| 日韩一区二区精品| 99国产麻豆精品| 亚洲欧美成人综合| 久久久久国产一区二区| 美脚丝袜一区二区三区在线观看| 牛牛影视久久网| 欧美人交a欧美精品| 国产精品欧美风情| 樱桃国产成人精品视频| 亚洲美女色禁图| 篠田优中文在线播放第一区| 久久久久一区| 亚洲经典三级| 亚洲欧美日韩一区| 麻豆久久婷婷| 欧美亚男人的天堂| 狠狠色噜噜狠狠色综合久| 日韩亚洲视频| 久久久久成人网| 91久久精品国产91性色tv| 亚洲调教视频在线观看| 久久日韩粉嫩一区二区三区| 欧美日韩国产一区二区三区地区 | 你懂的成人av| 国产精品一区二区久久久| 在线观看成人av电影| 亚洲一区二区久久| 免费在线欧美黄色| 亚洲无线视频| 欧美福利专区| 国产在线不卡| 亚洲综合色噜噜狠狠| 免费毛片一区二区三区久久久| 一区二区三区 在线观看视频| 久久精品成人一区二区三区| 欧美日韩影院| 亚洲国产视频直播| 久久精品日韩一区二区三区| 亚洲乱码精品一二三四区日韩在线 | 久久久爽爽爽美女图片| 99国内精品| 欧美极品aⅴ影院| 一区二区三区在线观看国产| 午夜一区二区三区在线观看| 最近看过的日韩成人|