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

【AHOI2013復仇】SCOI2008 斜堆

Posted on 2012-10-07 11:02 Mato_No1 閱讀(3085) 評論(1)  編輯 收藏 引用 所屬分類: 其它高級數據結構SCOI
一開始想傻了囧……不過很快就發現這其實是個超級大水題……
考慮斜堆中最后插入的那個結點,容易發現:
(1)它一定是一個極左結點(就是從根往它的路上一直都是沿著左鏈走),因為插入的時候每次都是插入到左子樹中;
(2)它一定木有右子樹,因為插入的時候每次都是把原來的某棵子樹作為新結點的左子樹;

滿足(1)(2)的結點可能有多個,但緊接著可以發現,這個斜堆中的每個結點如果木有左子結點,那么也木有右子結點(或者說,每個非葉結點都有左子樹),而在插入一個結點之前,其所有的祖先都被交換了左右子樹,所以,若新結點的祖先中有滿足(1)(2)的,且新結點不是葉結點,那么在新結點插入之前,這個滿足(1)(2)的祖先必然是只有右子樹而木有左子樹的,這與上面的那個性質矛盾,所以,可以得出:最后插入的那個結點一定是滿足(1)(2)的結點中,深度最小的那個(設為X),除非X的左子結點是葉結點,此時為了滿足字典序最小,應該取X的左子結點為最后插入的。找到這個最后插入的結點以后,只需要把它刪掉,并把它的所有祖先交換左右子樹,就是插入該結點以前的狀態了。這樣可以找到字典序最小的插入順序。
———————————————————————————————————————————————————
但是,這個題的意義還不止于此,必須要搞清楚斜堆到底是什么,有什么應用囧……

斜堆是可合并堆的一種實現形式,其更穩定的實現是左偏樹(斜堆只能做到均攤logN,而左偏樹則可以嚴格做到每次操作O(logN))。
斜堆最典型的特點,上面已經說過了,如果一個結點沒有左子樹,那么它也一定沒有右子樹。這樣,大多數斜堆看上去是往左傾斜的(這也就是它的名字的由來……)。如果給每個結點加上一個距離值dist[],為該結點到它最近的沒有右子樹的子結點的距離,并且滿足任意結點的左子結點的距離值都不小于右子結點的距離值的話,就成了左偏樹囧……

可合并堆,顧名思義,它必須滿足兩個性質:(1)是堆,也就是每個結點的關鍵字都不大于(小頂堆)/不小于(大頂堆)其兩個子結點的關鍵字;(2)它必須在O(logN)時間內完成合并操作,即將兩個堆合并為一個,且合并成的堆仍滿足原來的性質。
斜堆的合并操作有點像某些函數式數據結構,但它并不會動用額外的空間。該合并操作使用遞歸實現,設兩個斜堆(小頂堆)的根結點為A、B,若A和B中的某一個為空,則返回另一個;若A和B均非空,則先將它們中關鍵字小的那個的右子樹與關鍵字大的那個的整棵樹合并,作為關鍵字小的那個的新的右子樹,然后,如果是左偏樹的話要更新dist,若dist不滿足“左不小于右”,還要交換左右子樹。

斜堆可以支持的操作有(指能在O(logN)時間內完成的操作):
(1)插入結點:(用合并實現);
(2)刪除任意結點:(將待刪除結點的兩棵子樹合并,取代原來的位置,若是左偏樹的話還要往上更新dist直到dist不變為止,某論文里有證明,每次刪除更新dist次數不會超過2logN);
(3)合并兩個斜堆;
(4)找最小/大值;
(5)求以某個結點為根的子樹大小(維護sz即可);

斜堆不能支持的操作有(指不能在O(logN)時間內完成的操作):
(1)查找任意結點。因此,若要刪除某個指定結點,則必須先用下標等索引到它;
(2)找第K小(如果這個都能實現的話,斜堆就可以替代平衡樹了囧……還是可合并平衡樹……);
(3)找某個結點所在樹的根結點(但是配合并查集+索引可以實現,詳見HDU1512);

至于編程復雜度方面……非常非常好寫!基本上一個合并操作就夠了,<10行(斜堆的好寫程度僅次于并查集和普通堆);
寫的之后有三個主要的易疵點:
(1)合并的時候別忘了更新一些東東,尤其別忘了返回根結點;
(2)(極易疵的!!)如果要刪除某個結點,必須把它的所有信息恢復到孤立結點的狀態,即斷開與原樹的一切聯系(pr、L、R全部置0),dist(如果是左偏樹)置0、sz置1;(3)下標從1開始,0號結點作特殊用途(dist值為-1,sz值為0),如果某個結點的pr、L、R不存在則為0;

例題(由于想穩定,本沙茶全都是用左偏樹寫的囧):
【1】HDU1512
基本操作題,配合并查集+索引找根即可;
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int MAXN = 100010, INF = ~0U >> 2;
int n, u[MAXN], rt[MAXN], V[MAXN], dist[MAXN], pr[MAXN], L[MAXN], R[MAXN], res;
int UFS_find(int x)
{
    
int tmp = x, r = x; while (u[r] >= 0) r = u[r]; while (x != r) {tmp = u[x]; u[x] = r; x = tmp;} return r;
}
void UFS_union(int s1, int s2, int rt0)
{
    
if (u[s1] >= u[s2]) {u[s1] = s2; u[s2]--; rt[s2] = rt0;} else {u[s2] = s1; u[s1]--; rt[s1] = rt0;}
}
int heap_union(int s1, int s2)
{
    
if (!s1) return s2; else if (!s2) return s1; else if (V[s1] >= V[s2]) {
        
int z = heap_union(R[s1], s2);
        R[s1] 
= z; pr[z] = s1; if (dist[L[s1]] < dist[z]) {int tmp = L[s1]; L[s1] = R[s1]; R[s1] = tmp;}
        dist[s1] 
= dist[R[s1]] + 1return s1;
    } 
else {
        
int z = heap_union(s1, R[s2]);
        R[s2] 
= z; pr[z] = s2; if (dist[L[s2]] < dist[z]) {int tmp = L[s2]; L[s2] = R[s2]; R[s2] = tmp;}
        dist[s2] 
= dist[R[s2]] + 1return s2;
    }
}
void prepare()
{
    dist[
0= -1; re1(i, n) {u[i] = -1; rt[i] = i; dist[i] = pr[i] = L[i] = R[i] = 0;}
}
void solve(int x, int y)
{
    
int s1 = UFS_find(x), s2 = UFS_find(y); if (s1 == s2) {res = -1return;}
    
int rt1 = rt[s1], rt2 = rt[s2];
    
int z1 = heap_union(L[rt1], R[rt1]); L[rt1] = R[rt1] = pr[z1] = 0;
    V[rt1] 
/= 2; z1 = heap_union(rt1, z1); pr[z1] = 0;
    
int z2 = heap_union(L[rt2], R[rt2]); L[rt2] = R[rt2] = pr[z2] = 0;
    V[rt2] 
/= 2; z2 = heap_union(rt2, z2); pr[z2] = 0;
    
int z = heap_union(z1, z2); pr[z] = 0;
    UFS_union(s1, s2, z);
    res 
= V[z];
}
int main()
{
    
int m, x0, y0;
    
while (scanf("%d"&n) != EOF) {
        re1(i, n) scanf(
"%d"&V[i]); prepare();
        scanf(
"%d"&m);
        re(i, m) {
            scanf(
"%d%d"&x0, &y0);
            solve(x0, y0);
            printf(
"%d\n", res);
        }
    }
    
return 0;
}


【2】HDU3031
綜合操作題,需要sz,同時也可以考察數據結構的綜合應用能力。
#include <iostream>
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
#include 
<algorithm>
using namespace std;
#define re(i, n) for (int i=0; i<n; i++)
#define re1(i, n) for (int i=1; i<=n; i++)
#define re2(i, l, r) for (int i=l; i<r; i++)
#define re3(i, l, r) for (int i=l; i<=r; i++)
#define rre(i, n) for (int i=n-1; i>=0; i--)
#define rre1(i, n) for (int i=n; i>0; i--)
#define rre2(i, r, l) for (int i=r-1; i>=l; i--)
#define rre3(i, r, l) for (int i=r; i>=l; i--)
#define ll long long
const int MAXN = 1000010, MAXM = 101, MAXLEN_M = 10010, INF = ~0U >> 2;
int n, m, len[MAXM], V0[MAXM][MAXLEN_M], root[2];
int V[MAXN], dist[MAXN], pr[MAXN], L[MAXN], R[MAXN], sz[MAXN];
bool FS;
void upd(int x)
{
    sz[x] 
= sz[L[x]] + sz[R[x]] + 1;
}
int heap_union(int s1, int s2)
{
    
if (!s1) return s2; else if (!s2) return s1; else if (V[s1] >= V[s2]) {
        
int s0 = heap_union(R[s1], s2);
        pr[s0] 
= s1; R[s1] = s0; if (dist[L[s1]] < dist[s0]) {int tmp = L[s1]; L[s1] = R[s1]; R[s1] = tmp;} dist[s1] = dist[R[s1]] + 1; upd(s1);
        
return s1;
    } 
else {
        
int s0 = heap_union(s1, R[s2]);
        pr[s0] 
= s2; R[s2] = s0; if (dist[L[s2]] < dist[s0]) {int tmp = L[s2]; L[s2] = R[s2]; R[s2] = tmp;} dist[s2] = dist[R[s2]] + 1; upd(s2);
        
return s2;
    }
}
void opr_T(int x)
{
    sort(V0[x], V0[x] 
+ len[x]); int root0 = n + 1;
    rre(i, len[x]) {
        n
++if (i == len[x] - 1) pr[n] = 0else pr[n] = n - 1if (i) L[n] = n + 1else L[n] = 0; R[n] = dist[n] = 0; V[n] = V0[x][i]; sz[n] = i + 1;
    }
    root[FS] 
= heap_union(root[FS], root0);
}
void opr_A(int x)
{
    V[root[FS]] 
+= x;
}
void opr_E(int x)
{
    
int root0 = root[FS], z0; pr[z0 = heap_union(L[root0], R[root0])] = 0; L[root0] = R[root0] = dist[root0] = 0; sz[root0] = 1; V[root0] = x;
    root[FS] 
= heap_union(z0, root0);
}
void opr_L()
{
    
int root0 = root[FS], z0; pr[z0 = heap_union(L[root0], R[root0])] = 0; L[root0] = R[root0] = dist[root0] = 0; sz[root0] = 1;
}
void opr_C()
{
    
int root0 = root[0], root1 = root[1];
    
if (V[root0] > V[root1]) {
        root[
0= heap_union(root0, root1); root[1= 0;
    } 
else if (V[root0] < V[root1]) {
        root[
1= heap_union(root0, root1); root[0= 0;
    }
}
int main()
{
    
int tests, sc0 = 0, sc1 = 0, P, tmp; char ssss[10];
    scanf(
"%d"&tests);
    re(testno, tests) {
        scanf(
"%d%d"&P, &m);
        re(i, m) scanf(
"%d"&len[i]);
        re(i, m) re(j, len[i]) scanf(
"%d"&V0[i][j]); n = root[0= root[1= 0; dist[0= -1; sz[0= 0; FS = 0;
        re(i, P) {
            scanf(
"%s", ssss);
            
if (ssss[0== 'T') {scanf("%d"&tmp); opr_T(--tmp);}
            
else if (ssss[0== 'A') {scanf("%d"&tmp); opr_A(tmp);}
            
else if (ssss[0== 'E') {scanf("%d"&tmp); opr_E(tmp);}
            
else if (ssss[0== 'L') opr_L(); else opr_C();
            FS 
= !FS;
        }
        printf(
"%d:%d\n", sz[root[0]], sz[root[1]]);
        
if (sz[root[0]] >= sz[root[1]]) sc0++else sc1++;
    }
    
if (sc0 > sc1) puts("HahahaI win!!"); else puts("I will be back!!");
    
return 0;
}

Feedback

# re: 【AHOI2013復仇】SCOI2008 斜堆  回復  更多評論   

2013-03-03 01:02 by This_poet
Orz!我畫了兩頁紙之后發現想丑了TAT……
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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电影| 麻豆精品视频在线| 亚洲一区二区三区涩| 日韩一级精品| 夜夜狂射影院欧美极品| 亚洲精品看片| 亚洲人www| 亚洲欧洲日韩综合二区| 最新高清无码专区| 一本大道久久精品懂色aⅴ| 最新中文字幕亚洲| 亚洲美女精品久久| 在线视频精品一区| 亚洲欧美日韩国产综合| 亚洲国产婷婷香蕉久久久久久| 国产伦精品一区| 国产日本欧美一区二区三区| 国产精品高精视频免费| 国产一区二区三区高清| 亚洲经典在线看| 亚洲综合精品自拍| 欧美成人精品影院| 99天天综合性| 蜜桃av一区二区| 欧美日韩在线精品| 伊人色综合久久天天| 亚洲午夜伦理| 欧美3dxxxxhd| 欧美在线免费播放| 国产精品另类一区| 亚洲精品中文在线| 中文在线一区| 欧美精品一区二区精品网| 欧美精品一级| 亚洲人成网站在线观看播放| 久久大逼视频| 亚洲少妇自拍| 欧美视频不卡| 亚洲伊人观看| 亚洲午夜精品久久久久久浪潮 | 夜夜精品视频| 亚洲激情视频在线| 另类酷文…触手系列精品集v1小说| 国产酒店精品激情| 欧美中文字幕不卡| 亚洲激情视频网站| 猛男gaygay欧美视频| 久久久免费av| 99av国产精品欲麻豆| 亚洲激情视频在线| 国产麻豆成人精品| 久久久www免费人成黑人精品| 亚洲综合社区| 亚洲国产精品t66y| 亚洲看片网站| 在线日本高清免费不卡| 亚洲日韩中文字幕在线播放| 欧美精品在线一区二区三区| 亚洲一区二区三区在线看| 欧美在线国产| 午夜欧美不卡精品aaaaa| 欧美一区二区免费| 一区二区三区国产在线| 久久精品国产69国产精品亚洲 | 亚洲一区二区三区在线看| 在线不卡a资源高清| 99亚洲视频| 亚洲黄色三级| 狂野欧美一区| 久久激情网站| 黄色精品免费| 午夜国产精品影院在线观看| 亚洲精品综合精品自拍| 亚洲精品久久久一区二区三区| 久久天天躁狠狠躁夜夜av| 欧美激情二区三区| 欧美成人一区二区三区在线观看| 国产欧美在线视频| 亚洲一区二区三区免费视频| 亚洲一区二区综合| 欧美影院在线| 久久综合狠狠| 欧美三级乱码| 亚洲美女av黄| 日韩视频永久免费观看| 欧美顶级大胆免费视频| 夜夜嗨av一区二区三区网站四季av| 欧美激情bt| 欧美日韩精品是欧美日韩精品| 亚洲婷婷在线| 午夜精品久久久久久久99热浪潮 | 激情视频一区二区| 美女露胸一区二区三区| 欧美剧在线观看| 久久久www成人免费精品| 欧美国产日韩一区二区在线观看| 亚洲欧美三级在线| 久久一区二区三区超碰国产精品| a91a精品视频在线观看| 亚洲欧美亚洲| 一本色道久久88精品综合| 亚洲永久在线观看| 亚洲精品国精品久久99热| 亚洲一区二区三区免费视频 | 欧美日韩1区2区3区| 欧美专区一区二区三区| 免费在线日韩av| 欧美中文字幕在线| 欧美另类变人与禽xxxxx| 久久久久久9999| 欧美午夜在线| 亚洲区一区二| 尤妮丝一区二区裸体视频| 一区二区三区高清视频在线观看| 在线观看91久久久久久| 亚洲欧美在线观看| 亚洲一区久久久| 欧美日韩国产成人| 欧美黄色影院| 亚洲电影免费| 久久九九99视频| 午夜视频在线观看一区二区三区 | 在线观看成人av| 欧美一区激情| 欧美在线三级| 国产欧美综合一区二区三区| 亚洲午夜国产一区99re久久| 一区二区欧美亚洲| 欧美精品一区二区三| 亚洲国产成人精品久久久国产成人一区 | 亚洲欧美日韩精品久久奇米色影视| 亚洲国产91色在线| 久久久欧美一区二区| 久久精品国产91精品亚洲| 欧美性大战久久久久久久| 亚洲人成网站777色婷婷| 亚洲激情啪啪| 欧美久久久久久久久| 亚洲日韩成人| 亚洲一区二区三区涩| 国产精品久久久久一区二区三区共 | 99国产精品99久久久久久粉嫩| 老司机精品视频网站| 免费久久99精品国产| 极品av少妇一区二区| 久久久在线视频| 欧美大片在线观看| 亚洲美女尤物影院| 欧美日韩亚洲一区| 亚洲香蕉伊综合在人在线视看| 亚洲欧美日韩精品久久亚洲区| 国产精品亚洲激情| 欧美永久精品| 亚洲国产成人av好男人在线观看| 99精品视频免费| 国产精品网站在线观看| 久久黄色影院| 亚洲成人在线网| 亚洲午夜av电影| 国产亚洲精品aa| 六月丁香综合| 一本色道久久综合亚洲精品按摩 | 99精品视频免费观看| 国产精品久久看| 久久人人爽国产| 亚洲伦伦在线| 久久九九国产精品怡红院| 亚洲国产精品女人久久久| 欧美日韩性视频在线| 欧美一区二区私人影院日本| 欧美国产视频一区二区| 亚洲影音一区| 亚洲国产精品第一区二区| 国产精品s色| 老司机aⅴ在线精品导航| 亚洲私人影院在线观看| 欧美成人国产一区二区| 亚洲欧美另类在线观看| 影音先锋另类| 欧美亚韩一区| 欧美国产日韩xxxxx| 欧美尤物一区| 一本色道久久综合亚洲二区三区| 美日韩精品视频| 小黄鸭精品aⅴ导航网站入口| 亚洲精品日产精品乱码不卡| 国产一区二区高清| 国产精品黄视频| 欧美日韩不卡视频| 久久综合亚州| 久久不射中文字幕| 欧美午夜视频| 欧美成人官网二区| 欧美与欧洲交xxxx免费观看| 亚洲精品欧美日韩专区| 国产真实乱子伦精品视频| 欧美性事在线| 欧美日韩三级视频|