1. 程式人生 > >bzoj 1078 [SCOI2008] 斜堆

bzoj 1078 [SCOI2008] 斜堆

題目傳送門

  傳送點I

  傳送點II

題目大意

  給定一個(小根)斜堆的生成方式。

  1. 如果$H$為空,或者插入的數$x$的權值小於根節點的權值,那麼用$x$頂替$H$的位置,然後把$H$作為它的左子樹。
  2. 否則交換$H$根的左右子樹,然後遞迴左子樹。

  給定一個斜堆,元素大小分別為$0, 1, \dots, n$,問字典序最小的插入序列。

  (這篇隨筆可能不太嚴謹。)

  考慮倒著做這麼一個操作。不難發現下面這兩條:

引理1 斜堆$H$中所有非葉節點必然存在左子樹。

  證明 假設存在一個非葉節點$x$不存在左子樹,那麼它一定只存在右子樹。

  顯然它不可能比它右子樹中某個點$y$晚插入,因為插入$y$的時候,原來的右子樹變成了左子樹,之後一定存在。

  同時它也不可能比它右子樹中某個點$y$之前插入,因為插入$x$的時候,$y$會在$x$的左子樹中,再次插入後面的點的時候,左子樹一定存在。

  因此它不存在右子樹。與它是非葉節點矛盾。

  然後不難得到:

定理2.1 當新插入的點是非葉節點的時候,它的所有父節點都有右子樹,當新插入的點是葉節點的時候

定理2.2 當新插入的點是葉節點的時候,它的父節點的所有父節點都有右子樹。

  證明 設新插入的點為$x$。

  • 當$x$不是葉節點的時候,它的父節點存在同時存在左右子樹。假設它的$k$級祖先存在,並同時存在左右子樹,當$k + 1$級祖先存在的時候,推得$k + 1$級祖先存在右子樹,所以$k + 1$級祖先同時存在左右子樹。因此定理2.1得證。
  • 當$x$是葉節點的時候,它的父節點原本是葉節點或只存在左子樹。剩下的一樣。

  然後再討論一下還有哪些特點

定理3 新插入的點必定滿足:

  • 在最左鏈上
  • 不存在右子樹

  這兩點都比較顯然。由插入做法易證。

定理4 一個二叉樹$H$能通過斜堆車插入方式得到的充分必要條件是:

  1. 滿足堆性質
  2. 要麼是葉節點,要麼存在左子樹。

  證明  必要性 第一點顯然,第二點由引理1可證。

  充分性 當點數為1的時候,顯然成立。假設當點數不超過$k$時成立,考慮當點數為$k + 1$的時候。

  當根節點右子樹為空,因為左子樹是能夠構造出來,可以先建出左子樹,然後再插入根節點。

  否則我們考慮當前最後一個插入的點,由定理3可以知道它存在於當前根的左子樹中。

  一個插入序列在滿足根節點同時存在左右子樹之後,只是交替著向兩個子樹中插入元素。

  假設知道了左子樹和右子樹的插入序列(根據歸納假設我們知道它是存在的)。 

  顯然插入操作是可逆的,我們交替著撤銷左右子樹的插入,直到根沒有同時存在兩棵子樹,這時候根一定不存在右子樹(刪完最後一個點,然後交換左右子樹,所以右子樹為空)。

  此時把根刪掉。然後可以繼續按照左子樹的插入序列構造剩下的左子樹。

  然後我們就倒著構造出了插入序列。

定理5 一個點能成為最後一個插入的點的充分必要條件是:

  1. 在最左鏈上
  2. 不存在右子樹
  3. 當是葉節點時,父節點的所有父節點存在右子樹,當是非葉節點時,它的所有父節點存在右子樹

  證明 必要性由以上討論可知。

  充分性 由定理4必要性可知,每個非葉點均存在左子樹並且滿足堆性質。

  當它是葉節點的時候把它刪掉,然後交換它所有的祖先的左右子樹。它的父節點要麼變成葉節點要麼只存在左子樹。因為它父節點的祖先均在右子樹,所以左子樹非空。其他點不受影響,所以所有非葉節點存在左子樹。顯然仍然滿足堆性質。由定理4可知剩下的樹能夠通過斜堆的插入方法得到。

  當把這個點的左子樹變為它的父節點的左子樹,然後把這個點刪掉後,仍然滿足堆性質。類似地可以證明。

  我們仔細發現,可能成為最後一個插入的點只至多可能有2個。當最左鏈的葉節點的父節點滿足時存在兩個,否則只存在一個。

  為了使得字典序最小,我們考慮討論第一種情況。無論發現最後一個是哪一個點,撤銷它的插入後,剩下的樹的形態都一樣。

  所以對於其中一個的合法插入序列,交換這兩個數的位置,仍然成立。

  所以一定是後插入較大的數。(不然我就交換這兩個數,然後可以得到字典序更小的插入序列)。

  然後做法就變得異常簡單:

  1. 找到最左鏈上深度最大的滿足條件的點
  2. 刪掉它,加入到插入序列,然後交換它的所有父節點的左右子樹。

Code

 1 /**
 2  * bzoj
 3  * Problem#1078
 4  * Accepted
 5  * Time: 4ms
 6  * Memory: 1304k
 7  */
 8 #include <iostream>
 9 #include <cstdlib>
10 #include <cstdio>
11 using namespace std;
12 typedef bool boolean;
13 
14 const int N = 1e3 + 5;
15 
16 int n;
17 int ch[N][2];
18 int fa[N];
19 
20 inline void init() {
21     scanf("%d", &n);
22     fa[0] = -1;
23     for (int i = 1, d; i <= n; i++) {
24         scanf("%d", &d);
25         if (d < 100)
26             fa[i] = d, ch[d][0] = i;
27         else
28             d -= 100, fa[i] = d, ch[d][1] = i;
29     }
30 }
31 
32 int res[N];
33 inline void solve() {
34     int m = n;
35     int rt = 0;
36     while (n) {
37         int p = rt;
38         while (ch[p][1])
39             p = ch[p][0];
40         int s = ch[p][0];
41         if (!ch[s][0])
42             p = s;
43         res[n--] = p;
44 
45         int x = fa[p];
46         if (ch[p][0])
47             fa[ch[p][0]] = fa[p];
48         if (x >= 0) {
49             ch[x][0] = ch[p][0];
50             while (~x) {
51                 swap(ch[x][0], ch[x][1]);
52                 x = fa[x];
53             }
54         } else
55             rt = ch[p][0];
56     }
57     res[0] = rt;
58     for (int i = 0; i <= m; i++)
59         printf("%d ", res[i]);
60 }
61 
62 int main() {
63     init();
64     solve();
65     return 0;
66 }

相關推薦

bzoj 1078 [SCOI2008]

題目傳送門   傳送點I   傳送點II 題目大意   給定一個(小根)斜堆的生成方式。 如果$H$為空,或者插入的數$x$的權值小於根節點的權值,那麼用$x$頂替$H$的位置,然後把$H$作為它的左子樹。 否則交換$H$根的左右子樹,然後遞迴左子樹。   給定一個斜堆,元素大小

[SCOI2008]

esp 大於 clu 解法 相同 復雜度 times 題目 反轉 題目大意 1.題目描述 斜堆(skew heap)是一種常用的數據結構。 它也是二叉樹,且滿足與二叉堆相同的堆性質: 每個非根結點的值都比它父親大。因此在整棵斜堆中,根的值最小。 . 但斜堆不必是平衡的,每個

【BZOJ1078】[SCOI2008](性質題)

max turn str return name als oid 題目 getc 【BZOJ1078】[SCOI2008]斜堆(性質題) 題面 BZOJ 洛谷 題解 考慮一下這道題目的性質吧。思考一下最後插入進來的數是什麽樣子的。首先因為它是最後插入進來的,所以一定是比某個

bzoj1078: [SCOI2008]

題目 題解 考慮斜堆中最後插入的那個結點,容易發現: (1)它一定是一個極左結點(就是從根往它的路上一直都是沿著左鏈走),因為插入的時候每次都是插入到左子樹中; (2)它一定木有右子樹,因為插入的時候每次都是把原來的某棵子樹作為新結點的左子樹; 滿足(1)(2)的結點可能有多個,

[BZOJ 1076][SCOI2008]獎勵關(期望+狀壓Dp)

方便 double spa solution bsp 所有 一個 int stream Description 你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裏,系統將依次隨機拋出k次寶物, 每次你都可以選擇吃或者不吃(必須在拋出下一個寶物之前做出選

bzoj 1079: [SCOI2008]著色方案

我沒 組合 滿足 b- col line 模擬 lose 同學 1079: [SCOI2008]著色方案 2017-08-26 Description   有n個木塊排成一行,從左到右依次編號為1~n。你有k種顏色的油漆,其中第i種顏色的油漆足夠塗ci個木塊。所有油漆

bzoj 1076: [SCOI2008]獎勵關

目前 sin 最大 ios 有一個 決定 cpp 正在 gpo Description 你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裏,系統將依次隨機拋出k次寶物,每次你都可以選擇吃或者不吃(必須在拋出下一個寶物之前做出選擇,且現在決定不吃的寶物以後也不

並不對勁的

typedef struct nbsp 理解 none href 元素 div htm 為了反駁隔壁很對勁的太刀流,並不對勁的片手流將與之針鋒相對。 很對勁的斜堆、左偏樹簡明教程 它們是可並堆的兩種實現方式。 (假裝二叉堆只包括小根堆。) 二叉堆該如何合並?先想一種暴力的。

BZOJ 1079: [SCOI2008]著色方案(巧妙的dp)

result ret stdout 方案 code get 有一種 using spa BZOJ 1079: [SCOI2008]著色方案(巧妙的dp) 題意:有\(n\)個木塊排成一行,從左到右依次編號為\(1\)~\(n\)。你有\(k\)種顏色的油漆,其中第\(i\

深度解析(十二)

fin 內容 保存 source 測試 java版 AI root stat 斜堆(一)之 C語言的實現 概要 本章介紹斜堆。和以往一樣,本文會先對斜堆的理論知識進行簡單介紹,然後給出C語言的實現。後續再分別給出C++和Java版本的實現;實現的語言雖不同,但是原理如出一轍

BZOJ 1080: [SCOI2008]劣質編碼

技術 wid mes AC == its ++i In DC 這題我會暴力。。。如果時限 1e9 的話就可以過啦 這題 clj 也會暴力。。。然後他就秒 A 了。。。 (果然是蒟蒻 vs 大神) 大神的暴力簡直不可用語言來描述了。。。 #include <bits/

11、【

print str template new oid 以及 roo cout 當前 一、斜堆的介紹 斜堆(Skew heap)也叫自適應堆(self-adjusting heap),它是左傾堆的一個變種。和左傾堆一樣,它通常也用於實現優先隊列。它的合並操作的時間復雜度也是O

BZOJ 1077: [SCOI2008]天平

題面 題意 有n個砝碼,每個砝碼的質量為1g,2g或3g,但你不知道每個砝碼的具體質量是多少,但你知道它們某幾對砝碼之間的大小關係,先將兩個砝碼A,B放在天平左邊,請你再選兩個砝碼放在天平右邊,求有多少種選法使得天平的左邊重、一樣重、右邊重?(只有結果保證惟一的選法才統計在內)

【模板】

如題這是一個模板。。。 1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <cctyp

BZOJ 4919 大根【set啟發式合併 維護樹上LIS】

傳送門 題意: 對於一顆有點權的樹, 如果i是j的祖先, 那麼要滿足vi > vj, 問最多可以在這棵樹上選擇多少個點可以滿足這個條件. 思路: 那麼這就是樹上lis,怎麼維護了, 每個點依舊像普

[Luogu P2507] [BZOJ 1237] [SCOI2008]配對

洛谷傳送門 題目描述 你有 nnn 個整數AiA_iAi​和 nnn 個整數BiB_iBi​。你需要把它們配對,即每個AiA_iAi​恰好對應一個Bp[i]B_{p[i]}Bp[i]​。要求所有配對的

BZOJ 1076 [SCOI2008]獎勵關【狀態壓縮】【期望DP】

基於hzwer的部落格。 lim[i]lim[i]lim[i]表示可以獲得iii得前提。 考慮倒推,當前狀態的期望=(上一個狀態的期望+這次得到的價值)/概率 #include <bits/stdc++.h> #define db double #d

[bzoj 1076][SCOI2008]獎勵關

pan 遊戲 表示 bold paper esc max efi 決定 傳送門 Description 你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裏,系統將依次隨機拋出k次寶物, 每次你都可以選擇吃或者不吃(必須在拋出下一個寶物之前做出選擇,

BZOJ 1076([SCOI2008]獎勵關-期望dp-從後向前)

1076: [SCOI2008]獎勵關 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 328  Solved: 199 [Submit][Status][Discuss] Description 你正在玩你最喜歡的電子遊

bzoj 1076: [SCOI2008]獎勵關 (期望dp)

1076: [SCOI2008]獎勵關 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1814  Solved: 992 [Submit][Sta