日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

bzoj1078【SCOI2008】斜堆

發(fā)布時間:2025/4/16 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bzoj1078【SCOI2008】斜堆 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題意:

? ? ? 斜堆(skew heap)是一種常用的數(shù)據(jù)結(jié)構(gòu)。它也是二叉樹,且滿足與二叉堆相同的堆性質(zhì):每個非根結(jié)點的值都比它父親大。因此在整棵斜堆中,根的值最小。但斜堆不必是平衡的,每個結(jié)點的左右兒子的大小關(guān)系也沒有任何規(guī)定。在本題中,斜堆中各個元素的值均不相同。 在斜堆H中插入新元素X的過程是遞歸進行的:當(dāng)H為空或者X小于H的根結(jié)點時X變?yōu)樾碌臉涓?#xff0c;而原來的樹根(如果有的話)變?yōu)閄的左兒子。當(dāng)X大于H的根結(jié)點時,H根結(jié)點的兩棵子樹交換,而X(遞歸)插入到交換后的左子樹中。 給出一棵斜堆,包含值為0~n的結(jié)點各一次。求一個結(jié)點序列,使得該斜堆可以通過在空樹中依次插入這些結(jié)點得到。如果答案不惟一,輸出字典序最小的解。輸入保證有解。

輸入:

  第一行包含一個整數(shù)n。第二行包含n個整數(shù)d1, d2, ... , dn, di < 100表示i是di的左兒子,di>=100表示i
是di-100的右兒子。顯然0總是根,所以輸入中不含d0。

輸出:

  僅一行,包含n+1整數(shù),即字典序最小的插入序列。

Sample0.in

6
100 0 101 102 1 2

Sample0.out

0 1 2 3 4 5 6

?

Sample1.in

12?
0 101 1 2 3 105 6 4 104 102 10 5

Sample1.out

2 4 1 6 10 7 9 5 11 12 8 3 0

?

Sample2.in

12?
100 0 102 101 1 2 3 107 8 7 108 5

Sample2.out

8 11 9 7 0 1 10 5 3 4 2 12 6

?

調(diào)了一天QAQ

orz mato神犇 @http://www.cppblog.com/MatoNo1/archive/2013/03/03/192131.html

性質(zhì)1:若一個節(jié)點沒有左兒子,則該節(jié)點一定沒有右兒子。

    ?因為右兒子是由左兒子旋轉(zhuǎn)得到的,而在旋轉(zhuǎn)的同時左邊一定被插入節(jié)點了。

性質(zhì)2:最后一次插入一定插到極左節(jié)點(一直往左走),顯然得證。

性質(zhì)3:最后一次插入節(jié)點一定沒有右子樹,因為它在插入時一定是將原來的某棵子樹(可以為空)作為它的左子樹。

所以最后插入的節(jié)點一定是滿足性質(zhì)2,3的深度最小的節(jié)點,刪除該點后將其父親到跟的左右子樹交換。

因為如果不選深度最小的,則在交換的時候一定會交換到?jīng)]有右子樹的點,不滿足性質(zhì)1。

特例:若深度最小的滿足性質(zhì)2,3的節(jié)點有左兒子且其左兒子為葉子節(jié)點,則選其左兒子(字典序最小)

   因為刪除其左兒子后該點左右子樹為空,滿足性質(zhì)1

所以就不斷找最后加入的節(jié)點即可,記得考慮在刪除根后的影響(我因為這個WA了一下午),還有-1邊界的判定

#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int Mx=310; int n,tot,top,fa[Mx],l[Mx],r[Mx],ans[Mx]; void find(int root) {if(r[root]!=0&&l[root]!=0) find(l[root]);else if(l[root]!=0&&l[l[root]]==0&&r[l[root]]==0&&r[root]==0){ans[++tot]=l[root];l[root]=0;}else if(r[root]==0){ans[++tot]=root;if(l[root]!=0) fa[l[root]]=fa[root];if(fa[root]==-1) top=l[root];else l[fa[root]]=l[root];}if(fa[root]!=-1) swap(l[fa[root]],r[fa[root]]); } int main() {scanf("%d",&n);fa[0]=-1;for(int i=1;i<=n;i++){int d;scanf("%d",&d);if(d<100) fa[i]=d,l[d]=i;else fa[i]=d-100,r[d-100]=i;}while(tot!=n) find(top); cout<<top<<" ";for(int i=tot;i>=1;i--) cout<<ans[i]<<" ";return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/xiaoxubi/p/6243888.html

總結(jié)

以上是生活随笔為你收集整理的bzoj1078【SCOI2008】斜堆的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。